Intro To Arduino
Intro To Arduino
What is Arduino?
An introduction to what Arduino is, and what it can be used for.
Last revision10/28/2024
Over the years Arduino has been the brain of thousands of projects, from
everyday objects to complex scientific instruments. A worldwide community
of makers - students, hobbyists, artists, programmers, and professionals -
has gathered around this open-source platform, their contributions have
added up to an incredible amount of accessible knowledge that can be of
great help to novices and experts alike.
Arduino was born at the Ivrea Interaction Design Institute as an easy tool
for fast prototyping, aimed at students without a background in electronics
and programming. As soon as it reached a wider community, the Arduino
board started changing to adapt to new needs and challenges,
differentiating its offer from simple 8-bit boards to products for IoT
applications, wearable, 3D printing, and embedded environments.
Why Arduino?
Thanks to its simple and accessible user experience, Arduino has been used
in thousands of different projects and applications. The Arduino software is
easy-to-use for beginners, yet flexible enough for advanced users. It runs
on Mac, Windows, and Linux. Teachers and students use it to build low cost
scientific instruments, to prove chemistry and physics principles, or to get
started with programming and robotics. Designers and architects build
interactive prototypes, musicians and artists use it for installations and to
experiment with new musical instruments. Makers, of course, use it to build
many of the projects exhibited at the Maker Faire, for example. Arduino is a
key tool to learn new things. Anyone - children, hobbyists, artists,
programmers - can start tinkering just following the step by step
instructions of a kit, or sharing ideas online with other members of the
Arduino community.
Open source and extensible hardware - The plans of the Arduino boards are
published under a Creative Commons license, so experienced circuit
designers can make their own version of the module, extending it and
improving it. Even relatively inexperienced users can build the breadboard
version of the module in order to understand how it works and save money.
The text of the Arduino getting started guide is licensed under a Creative
Commons Attribution-ShareAlike 3.0 License. Code samples in the guide are
released into the public domain.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
Why Arduino?
How do I use Arduino?
AuthorLiam Aljundi
Last revision10/28/2024
Welcome to Arduino! Before you start controlling the world around you,
you'll need to set up the software to program your board.
IDE
An Integrated Development Environment (IDE) is a software that allows you
to write code and upload it to your Arduino hardware. We have our
own [Arduino Software (IDE)]
(https://www.arduino.cc/en/software application available for Windows,
macOS and Linux users. Besides the convenient code editing functions, the
Arduino Software (IDE) is equipped with a list of libraries that provide extra
functionality for use in sketches, making it easier for you to connect
sensors, displays, modules, etc.
Arduino Tools
You can write programs and upload them to your board with the browser
IDE (Arduino Cloud Editor), or the desktop one (Arduino Software IDE).
Another option is to use the Arduino Cloud web platform if you are
interested in creating IoT systems and have a compatible board. Here are
some tips to help you pick the best tool to suit your needs:
1. If you have a reliable Internet connection, you should use the online
IDE (Arduino Cloud Editor). It will allow you to save your sketches in the
Cloud, having them available from any device and backed up. Also, you will
always have the most up-to-date version of the IDE without the need to
install updates or community generated libraries.
2. If you would rather work offline, you should use the latest version of
the desktop IDE (Arduino Software IDE).
3. If you wish to create our very own IoT project, you should use
the Arduino Cloud. It will allow you to track data in real time, trigger remote
devices and build wireless systems.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
IDE
Arduino Tools
The Arduino Software (IDE) makes it easy to write code and upload it to the
board offline. We recommend it for users with poor or no internet
connection. This software can be used with any Arduino board.
There are currently two versions of the Arduino IDE, one is the IDE 1.x.x and
the other is IDE 2.x. The IDE 2.x is new major release that is faster and even
more powerful to the IDE 1.x.x. In addition to a more modern editor and a
more responsive interface it includes advanced features to help users with
their coding and debugging.
The following steps can guide you with using the offline IDE (you can
choose either IDE 1.x.x or IDE 2.x):
Arduino IDE 1.x.x (Windows, Mac OS, Linux, Portable IDE for
Windows and Linux, ChromeOS).
Arduino IDE 2.x
2. The message area, gives feedback while saving and exporting and also
displays errors.
4. The text console displays text output by the Arduino Software (IDE),
including complete error messages and other information.
The bottom right-hand corner of the window displays the configured board
and serial port.
Now that you are all set up, let’s try to make your board blink!
Selecting a board
7. Now, let's make sure that your board is found by the computer,
by selecting the port. This is simply done by navigating to Tools > Port,
where you select your board from the list.
Selecting the port
8. Let’s try an example: navigate to File > Examples > 01.Basics >
Blink.
Opening an example
9. To upload it to your board, simply click on the arrow in the top left
corner. This process takes a few seconds, and it is important to not
disconnect the board during this process. If the upload is successful, the
message "Done uploading" will appear in the bottom output area.
10. Once the upload is complete, you should then see on your board the
yellow LED with an L next to it start blinking. You can adjust the speed of
blinking by changing the delay number in the parenthesis to 100, and
upload the Blink sketch again. Now the LED should blink much faster.
Congratulations! You have successfully programmed your board to blink
its on-board LED! You can find more information about the Arduino Software
(IDE) 2.x here.
2. The Sidebar for regularly used tools. It gives you quick access to board
managers, libraries, debugging your board as well as a search and
replacement tool.
5. The text console displays text output by the Arduino Software (IDE),
including complete error messages and other information.
The bottom right-hand corner of the window displays the configured board
and serial port.
The Arduino Software IDE
Now that you are all set up, let’s try to make your board blink!
2. Now, you need to select the right board & port. This is done from the
toolbar. Make sure you select the board that you are using. If you cannot
find your board, you can add it from the board manager in the sidebar.
Selecting a board & port
3. Let’s try an example: navigate to File > Examples > 01.Basics >
Blink.
Opening an example
4. To upload it to your board, simply click on the arrow in the top left
corner. This process takes a few seconds, and it is important to not
disconnect the board during this process. If the upload is successful, the
message "Done uploading" will appear in the bottom output area.
5. Once the upload is complete, you should see on your board the yellow
LED with the letter L next to it, start blinking. You can adjust the speed of
blinking by changing the delay number in the parenthesis to 100, and
upload the Blink sketch again. Now the LED should blink much faster.
Congratulations! You have successfully programmed your board to blink
its on-board LED! You can find more information about the Arduino Software
(IDE) here.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
AuthorLiam Aljundi
Last revision10/28/2024
The Arduino Cloud Editor allows you to write code and upload sketches to
any official Arduino board directly from your web browser (Chrome, Firefox,
Safari and Edge). However, we recommend you use Google Chrome.
3. The third column, the code area, is the one you will use the most. Here,
you can write code, verify it and upload it to your boards, save your
sketches on the Cloud, and share them with anyone you want.
Now that you are all set up, let’s try to make your board blink!
2. Let’s try an example: Choose Examples on the menu on the left (first
column), then Basic and Blink. The Blink sketch is now displayed in the code
area.
Finding an example
4. Once the upload is complete, you should see on your board the yellow
LED with an L next to it start blinking. You can adjust the speed of
blinking by changing the delay number in the parenthesis to 100, and
upload the Blink sketch again. Now the LED should blink much faster.
Congratulations! You have successfully programmed your board to blink
its on-board LED! You can find more information about the Arduino Cloud
Editor here.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
AuthorLiam Aljundi
Last revision10/28/2024
The Arduino environment can be extended through the use of libraries. Just
like most programming platforms, libraries provide extra functionality for
use in sketches, e.g. working with hardware or manipulating data. To use a
library in a sketch, select it from Sketch > Import Library.
Offline IDE
A number of libraries come installed with the IDE, but you can also
download or create your own. Here are some instructions for setting up a
library on the offline IDE:
1. Open the IDE and click "Sketch" on the menu tab and then Include
Library > Manage Libraries.
2. Search for the library that you need, click on it, then select the
version of the library you want to install.
A list of libraries on the library manager
3. Finally, click on install and wait for the IDE to install the new library.
Once it has finished, an Installed tag should appear next to the library of
your choice, so you can go ahead and close the library manager.
Now the new library will be available in the Sketch > Include
Library menu. If you want to add your own library to Library Manager,
follow these instructions.
Online IDE
The process of setting up libraries on the online IDE (Arduino Cloud
Editor) is quite similar to the offline one:
4. When you find the library, you can add it to your sketch by selecting
the "Include" button. You can also see the related examples, and select a
specific version, if available.
5. If you can't find a specific library on the list, you can search every
existing library through the search bar. You also have the option to add
them to your favorites list by clicking on the star next to the library you
want. Once you star a library, you can view it under the "favorites" tab and
use its examples (if available).
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
Offline IDE
Online IDE
AuthorLiam Aljundi
Last revision10/28/2024
Using the Arduino Cloud
With the Arduino Cloud desktop or mobile platform, you can quickly
connect, manage and monitor your devices from anywhere in the world.
Arduino Cloud allows you to automatically create any code to program your
device with - just add a couple of lines to customize it how you want. If
you’re new to Arduino don’t worry there’s example code for hundreds of
sensors and actuators.
The following steps will guide you to start using the Arduino Cloud:
2. Check if you have a cloud compatible board. The picture below shows
all official Arduino boards that are compatible.
Creating a Thing
1. The user journey always begins by creating a new Thing. In the Thing
overview, we can choose what device to use, what Wi-Fi network we want
to connect to, and create variables that we can monitor and control.
Arduino Cloud’s interface
A special sketch file can now be found in the Sketch tab, which includes all
of the configurations that you have made. When the sketch has been
uploaded, it will work as a regular sketch, but it will also update the Cloud
variables that we use!
When we are happy with our sketch, we can upload it to our board, by
clicking the upload button.
After we have successfully uploaded the code, we can open the Serial
Monitor tab to view information regarding our connection. If it is
successful, it will print connected to network_name and connected to
cloud.
If it fails to connect, it will print the errors here as well. Now that we have
configured the device & network, created variables, completed the sketch
and successfully uploaded the code, we can move on to the fun part,
the dashboard!
Creating the dashboard
Dashboards are visual user interfaces for interacting with your boards over
the Cloud, and we can set up many different setups depending on what
your IoT project needs.
Once it is linked, we can either interact with it, for example a button, or we
can monitor a value from a sensor. As long as our board is connected to the
Cloud, the values will update automatically!
Congratulations! Now you are ready to create your own IoT system. You
can find more information about the Arduino Cloud here.
Network Configuration
Note: that the Arduino Cloud operates with different domains and ports, which means
that if we want devices working with the Arduino Cloud, they need to be allowed
access to certain domains through your firewall.
If you are connected to your school or university networks, please
provide your admin with the following instructions:
Por
Domain
t
mqtts- 888
up.iot.arduino.cc 4
mqtts- 888
sa.iot.arduino.cc 3
844
wss.iot.arduino.cc
3
If you are having issues connecting to the Arduino Cloud through your home
network, follow these instructions:
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
AuthorLiam Aljundi
Last revision10/28/2024
You can check the following suggestions to help you solve any potential
problem:
1. Make sure that you chose the right board and port, and have installed
all the drivers needed.
2. If you are still running into an error, you can copy the error message and
search it through our troubleshooting guide page .
3. If you cannot find any help through our troubleshooting guide page , you
can use our forum support for help.
Below you will find further guidance on the steps mentioned.
Make sure you have the right item selected in the Tools >
Board menu. If you have an Arduino UNO, you'll need to choose it.
Then, check that the proper port is selected in the Tools > Serial
Port menu (if your port doesn't appear, try restarting the IDE with the
board connected to the computer):
Drivers
Drivers provide a way for the software on your computer (i.e. the Arduino
software) to talk to any hardware you connect to it (i.e. the Arduino board).
The easiest way to check if the drivers for your board are installed correctly
is by opening the Tools > Serial Port menu in the Arduino software with
the Arduino board connected to your computer.
Additional menu items should appear relative to when you open the menu
without the Arduino connected to your computer. Note that it shouldn't
matter what name the Arduino board's serial port gets assigned as long as
that's the one you pick from the menu.
If you get this error when installing the UNO or Mega 2560 drivers
on Windows XP: "The system cannot find the file specified", you
might try this suggestion (about adding a "RunOnce" key to
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\
CurrentVersion").
On Linux, the UNO and Mega 2560 show up as devices of the form
/dev/ttyACM0. These are not supported by the standard version of the
RXTX library that the Arduino software uses for serial communication.
The Arduino software download for Linux includes a version of the
RXTX library patched to also search for these /dev/ttyACM* devices.
There's also an Ubuntu package (for 11.04) which includes support for
these devices. If, however, you're using the RXTX package from your
distribution, you may need to symlink from /dev/ttyACM0 to
/dev/ttyUSB0 (for example) so that the serial port appears in the
Arduino software.
Run:
Copy
Log off and log on again for the changes to take effect.
Troubleshooting Guide
In the Arduino Help Center you will find articles on frequently asked
questions, and troubleshooting guides for most of the errors you might
encounter. You can use our help center by browsing through the different
categories and the questions provided in each of them, or by searching
your error in the search tab.
Forum Support
If it still doesn't work, you can ask for help in the forum. Please include the
following information:
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
Last revision10/28/2024
Starting from the Arduino Software (IDE) version 1.6.2, all Arduino AVR
boards are installed by default. Some Arduino boards require an additional
core to be installed, therefore we have implemented the Boards
Manager as the preferred tool to add cores to your Arduino Software (IDE).
Boards manager will open and you will see a list of installed and available
boards; the download of the index file could take some time and the list
appears at the end of this process; please be patient.
Click on the Arduino SAM Boards core, choose the version in the drop-down
menu and click on Install.
If you have more JSON files to add, click on the little icon on the right of the
field and open a specific window where you may input more URLs, one line
at a time.
After this procedure, the new cores will be available for install in the Boards
Manager. Please refer to the information provided by the third party core
author to get more specific instructions.
The text of the Arduino getting started guide is licensed under a Creative
Commons Attribution-ShareAlike 3.0 License. Code samples in the guide are
released into the public domain.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
AuthorArduino
Last revision10/28/2024
The Arduino Comic was created by Jody Culkin and published during 2011.
You can download the original , but you can also help out and contribute
translating it to your own language.
Translations
ARABIC /عربي
Work files:
Right-to-left SVGs
Arabic work files
CATALAN / CATALÀ
Chinese / 中文
DUTCH / NEDERLANDS
DEUTSCH / GERMAN
DEVNAGARI / देवनागरी
FRENCH / français
GREEK / ΕΛΛΗΝΙΚΑ
Translated by: Anna Maragkoudaki
Email/url: rottyfish@yahoo.com
Greek PDF version
GUJARATI / ગુજરાતી
KOREAN / 한국어
Nepali / नेपाली
Persian / فارسی
PORTUGUESE / PORTUGUÊS
SPANISH / ESPAÑOL
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything
wrong, you can edit this page here.
Need support?
Help CenterAsk the Arduino ForumDiscover Arduino Discord
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike
4.0 license.
ON THIS PAGE
Arduino API
A reference to the Arduino Programming Language.
AuthorKarl Söderby
Last revision10/28/2024
Functions
Digital I/O
Retur
Method & Parameters Description
ns
state) pin. g
INPUT
(0)
OUTPUT
(1)
INPUT_PULLUP
(2)
INPUT_PULLDOWN
(3)
OUTPUT_OPENDRAIN
(4)
Analog I/O
Retur
Method & Parameters Description
ns
reference) board.** g
void analogWrite(int pin, int Writes a value to a PWM supported pin Nothin
Advanced I/O
Retur
Method & Parameters Description
ns
void tone(int pin, int Generates a square wave on specified pin, Nothin
long pulseInLong(int pin, int Returns the length of the pulse (in
long
state, long timeout) microseconds)
*The
bitOrder
parameter is either
MSBFIRST
) or
LSBFIRST
(
shiftOut()
needs to be configured as an
OUTPUT
, using
pinMode()
Time
Retur
Method & Parameters Description
ns
Retur
Method & Parameters Description
ns
Constrains a number to be
int constrain(int value, int min, int max) int
within a range.
long map(long val, long min, long max, Re-maps a number from one
long
long newMin, long newMax) range to another.
Characters
Retur
Method & Parameters Description
ns
method.
Random Numbers
Retur
Method & Parameters Description
ns
Retur
Method & Parameters Description
ns
Nothin
void bitClear(int &value, int bit) Clears a specific bit.
g
Nothin
void bitSet(int &value, int bit) Sets a specific bit.
g
void bitWrite(int &value, int bit, int Writes a value to a specific Nothin
bitValue) bit. g
int
External Interrupts
Retur
Method & Parameters Description
ns
Interrupts
Retur
Method & Parameters Description
ns
terminator, char *buffer, int buffer into a buffer until a terminator int
length) is found.
find()
findUntil()
void setTimeout(unsigned long Nothin
,
timeout) g
parseInt()
, and
parseFloat()
Serial
Retur
Method & Parameters Description
ns
int readBytes(char *buffer, size_t Reads characters from the serial buffer
int
length) into a buffer.
length) found.
timeout)
find()
findUntil()
parseInt()
, and
Retur
Method & Parameters Description
ns
parseFloat()
SPI
I2C (Wire)
Retur
Method & Parameters Description
ns
void setClock(uint32_t
Sets the I2C clock frequency. void
frequency)
void setWireTimeout(uint32_t
Sets the timeout for I2C operations. void
timeout)
Variables
Enums
Enum
Enumeration Description
Type
and
0
Enum
Enumeration Description
Type
).
).
Conversion
Method &
Description
Parameter
Data Types
Method &
Description
Parameter
Method &
Description
Parameter
Utilities
Method &
Description
Parameter
Structure
Sketch
Method &
Description
Parameter
Control Structure
Method &
Description
Parameter
Method &
Description
Parameter
// (single line
Single line comment.
comment)
Arithmetic Operators
Method &
Description
Parameter
operator)
Comparison Operators
Method &
Description
Parameter
< (less than) Checks if the left value is less than the right value.
<= (less than or equal Checks if the left value is less than or equal to the right
to) value.
> (greater than) Checks if the left value is greater than the right value.
>= (greater than or Checks if the left value is greater than or equal to the
Boolean Operators
Method &
Description
Parameter
&& (logical and) Logical AND operator, returns true if both operands are
Method &
Description
Parameter
true.
Method &
Description
Parameter
operator) pointer.
Bitwise Operators
Method &
Description
Parameter
Compound Operators
Method &
Description
Parameter
&= (compound Performs a bitwise AND operation and assigns the result
+= (compound Adds the right operand to the left operand and assigns the
-= (compound Subtracts the right operand from the left operand and
/= (compound Divides the left operand by the right operand and assigns
Last revision10/28/2024
pin
, whose value is
13
, and whose type is
int
. Later on in the program, you can refer to this variable by its name, at which point
its value will be looked up and used. For example, in this statement:
pinMode(pin, OUTPUT);
it is the value of pin (13) that will be passed to the pinMode() function. In
this case, you don't actually need to use a variable, this statement would
work just as well:
pinMode(13, OUTPUT);
The advantage of a variable in this case is that you only need to specify the
actual number of the pin once, but you can use it lots of times. So if you
later decide to change from pin 13 to pin 12, you only need to change one
spot in the code. Also, you can use a descriptive name to make the
significance of the variable clear (e.g. a program controlling an RGB LED
might have variables called redPin, greenPin, and bluePin).
pin = 12;
will change the value of the variable to 12. Notice that we don't specify the
type of the variable: it's not changed by the assignment. That is, the name
of the variable is permanently associated with a type; only its value
changes. [1] Note that you have to declare a variable before you can assign
a value to it. If you include the preceding statement in a program without
the first statement above, you'll get a message like: "error: pin was not
declared in this scope".
When you assign one variable to another, you're making a copy of its value
and storing that copy in the location in memory associated with the other
variable. Changing one has no effect on the other. For example, after:
Copy
3pin = 12;
Now what, you might be wondering, did the word "scope" in that error
message above mean? It refers to the part of your program in which the
variable can be used. This is determined by where you declare it. For
example, if you want to be able to use a variable anywhere in your
program, you can declare at the top of your code. This is called
a global variable; here's an example:
Copy
2void setup()
3{
4pinMode(pin, OUTPUT);
5}
6void loop()
7{
8digitalWrite(pin, HIGH);
9}
pin
is used in both the setup() and loop() functions. Both functions are referring to the
same variable, so that changing it one will affect the value it has in the other, as in:
Copy
2void setup()
3{
4pin = 12;
5pinMode(pin, OUTPUT);
6}
7void loop()
8{
9digitalWrite(pin, HIGH);
10}
Here, the digitalWrite() function called from loop() will be passed a value of
12, since that's the value that was assigned to the variable in the setup()
function.
If you only need to use a variable in a single function, you can declare it
there, in which case its scope will be limited to that function. For example:
Copy
1void setup()
2{
4pinMode(pin, OUTPUT);
5digitalWrite(pin, HIGH);
6}
In this case, the variable pin can only be used inside the setup() function. If
you try to do something like this:
Copy
1void loop()
2{
4}
you'll get the same message as before: "error: 'pin' was not declared in this
scope". That is, even though you've declared pin somewhere in your
program, you're trying to use it somewhere outside its scope.
Why, you might be wondering, wouldn't you make all your variables global?
After all, if I don't know where I might need a variable, why should I limit its
scope to just one function? The answer is that it can make it easier to figure
out what happens to it. If a variable is global, its value could be changed
anywhere in the code, meaning that you need to understand the whole
program to know what will happen to the variable. For example, if your
variable has a value you didn't expect, it can be much easier to figure out
where the value came from if the variable has a limited scope.
[1] In some languages, like Python®, types are associated with values, not
variable names, and you can assign values of any type to a variable. This is
referred to as dynamic typing.
Last revision10/28/2024
Functions codify one action in one place so that the function only has
to be thought out and debugged once.
This also reduces chances for errors in modification, if the code needs
to be changed.
Functions make the whole sketch smaller and more compact because
sections of code are reused many times. They make it easier to reuse code
in other programs by making it more modular, and as a nice side effect,
using functions also often makes the code more readable. There are two
required functions in an Arduino sketch, setup() and loop(). Other functions
must be created outside the brackets of those two functions. As an
example, we will create a simple function to multiply two numbers.
Example
Copy
1void loop(){
2int i = 2;
3int j = 3;
4int k;
Copy
1void setup(){
2 Serial.begin(9600);
3}
5void loop() {
6 int i = 2;
7 int j = 3;
8 int k;
11 Serial.println(k);
12 delay(500);
13}
14
16 int result;
17 result = x * y;
18 return result;
19}
Another example
This function will read a sensor five times with analogRead() and calculate
the average of five readings. It then scales the data to 8 bits (0-255), and
inverts it, returning the inverted result.
Copy
1int ReadSens_and_Condition(){
2 int i;
3 int sval = 0;
7 }
12 return sval;
13}
Copy
1int sens;
3sens = ReadSens_and_Condition();
As you can see, even if a function does not have parameters and no returns
is expected "(" and ")" brackets plus ";" must be given.
Arduino Sketches
Get to know how sketches work, and how they are uploaded to an Arduino.
Last revision10/28/2024
A sketch is the name that Arduino uses for a program. It's the unit of code
that is uploaded to and run on an Arduino board.
Comments
The first few lines of the Blink sketch are a comment:
Copy
1/*
3 * Blink
5*
9 * then off for one second, and so on... We use pin 13 because,
10
14
15 *
16
17 * http://www.arduino.cc/en/Tutorial/Blink
18
19 */
/*
and
*/
is ignored by the Arduino when it runs the sketch (the
*
at the start of each line is only there to make the comment look pretty, and isn't
required). It's there for people reading the code: to explain what the program does,
how it works, or why it's written the way it is. It's a good practice to comment your
sketches, and to keep the comments up-to-date when you modify the code. This
helps other people to learn from or modify your code.
There's another style for short, single-line comments. These start with
//
and continue to the end of the line. For example, in the line:
Copy
Variables
A variable is a place for storing a piece of data. It has a name, a type, and a
value. For example, the line from the Blink sketch above declares a variable
with the name
ledPin
, the type
int
, and an initial value of 13. It's being used to indicate which Arduino pin the LED is
connected to. Every time the name
ledPin
appears in the code, its value will be retrieved. In this case, the person writing the
program could have chosen not to bother creating the
ledPin
variable and instead have simply written 13 everywhere they needed to specify a
pin number. The advantage of using a variable is that it's easier to move the LED to
a different pin: you only need to edit the one line that assigns the initial value to the
variable.
Often, however, the value of a variable will change while the sketch runs.
For example, you could store the value read from an input into a variable.
There's more information in the Variables tutorial.
Functions
A function (otherwise known as a procedure or sub-routine) is a named
piece of code that can be used from elsewhere in a sketch. For example,
here's the definition of the
setup()
function from the Blink example:
Copy
1void setup()
2{
The first line provides information about the function, like its name, "setup".
The text before and after the name specify its return type and parameters:
these will be explained later. The code between the
{
and
}
is called the body of the function: what the function does.
You can call a function that's already been defined (either in your sketch or
as part of the Arduino language). For example, the line
pinMode(ledPin, OUTPUT);
calls the
pinMode()
function, passing it two parameters:
ledPin
and
OUTPUT
. These parameters are used by the
pinMode()
function to decide which pin and mode to set.
pinMode()
function configures a pin as either an input or an output. To use it, you pass it the
number of the pin to configure and the constant INPUT or OUTPUT. When configured
as an input, a pin can detect the state of a sensor like a pushbutton; this is
discussed in the Digital Read Serial tutorial . As an output, it can drive an actuator
like an LED.
The
digitalWrite()
functions outputs a value on a pin. For example, the line:
Copy
1digitalWrite(ledPin, HIGH);
set the
ledPin
(pin 13) to HIGH, or 5 volts. Writing a LOW to pin connects it to ground, or 0 volts.
The
delay()
causes the Arduino to wait for the specified number of milliseconds before
continuing on to the next line. There are 1000 milliseconds in a second, so the line:
Copy
1delay(1000);
setup()
and
loop()
. The
setup()
is called once, when the sketch starts. It's a good place to do setup tasks like
setting pin modes or initializing libraries. The
loop()
function is called over and over and is heart of most sketches. You need to include
both functions in your sketch, even if you don't need them for anything.
Exercises
1. Change the code so that the LED is on for 100 milliseconds and
off for 1000.
2. Change the code so that the LED turns on when the sketch starts
and stays on.
See Also
setup()
loop()
pinMode()
digitalWrite()
delay()
Last revision10/28/2024
Hardware Required
MKR Vidor 4000
As it happens with Software, where there are lots of libraries you can start
from, also for FPGAs there are "libraries" called IP blocks, however these
are usually quite expensive and lack a standardized "plug and play"
interface which causes headaches when integrating everything in a system.
What Arduino is trying to do introducing FPGAs in its product line is to take
advantage of the flexibility of programmable hardware specifically to
provide an extendable set of peripherals for microcontrollers taking away
most of the complexity. Of course to achieve this it's necessary to impose
some limitations and define a standard way to interconnect blocks so that it
can be done automatically.
The first step is defining a set of standard interfaces that must be strictly
responding to a given set of rules but before diving into this it's important
to define which kind of interfaces we may need. Since we are interfacing
with a microcontroller the first port we need to define is a bus to
interconnect processor with peripherals. Such bus should at least exist in
the controller and peripheral flavors where signals are the same but with
inverted directions. For some additional details on buses and
controller/peripheral architecture please check this document.
Finally there is a third class of interfaces which may become useful which
carries streaming data. In this case we want to transfer a continuous
stream of data but also want to be able to pause the flow if the receiving
block is not able to process it, hence along with data we also need some
kind of flow control signals pretty much like it happens on a UART.
Coding Conventions
We use a prefix in front of every declared entity so that it identifies its type,
variable name is completely upper case and multiple words are separated by
underscores. In particular:
Prefi
Description
x
Wire, for all combinatorial signals, for example wDATA. Typically defined
w
with wire directive
Reg, for all sequential signals, for example rSHIFTER. Typically defined
r
with reg directive
Input, for all input signals in module declaration, for example iCLK.
i
Typically defined with input directive
Output, for all output signals in module declaration, for example oREAD.
o
Typically defined with output directive
Parameter, for all parameters that can be used to parametrize block, for
p
example pCHANNELS. Typically defined with param directive
c Constant, for all definitions which are constant or are derived values and
Prefi
Description
x
Enumerated, for all the possible constant values used by one or more
e signals or registers. For example a state machine state can be defined as
eSTATE. Typically defined with enum directive
We prefer spaces over tabs! The reason is that regardless of the tab
size code always looks good.
Indentation is set to two spaces.
Conditional statement blocks shall always have begin/end constructs
even if they have a single statement in them and begin/end should be
on the same line of the if/else
Signals belonging to the same group shall share a common prefix
Interface prototypes
Lightweight Bus
A bus to interconnect peripherals. By convention data bus is 32 bits while
address bus is variable width, based on the number of registers being
exposed. A bus requires the following set of signals:
Controlle Periphera
r l
Directio Directio Widt
Signal Description
n n h
This behavior is also referred as 1 clock read latency and basically means
that while peripheral can still have a variable number of clocks to respond
to a READ or WRITE operation using the optional WAIT_REQUEST signal, this
would lock the controller preventing it to perform other operations. In a way
this can be considered similar to using busy loops in programming versus
delays which yield to OS in order to do multitasking.
Controlle Periphera
r l
Number of sequential
BURST_COUNT O I var.
operations to perform
Streaming interface
Coming soon
Copy
1module COUNTER #(
2pWIDTH=8
3) (
4input iCLK,
5input iRESET,
7);
8endmodule
Here we just defined the prototype of the module and defined its
input/output ports, now we have to add some useful logic to it by adding
some code between module header and the endmodule statement.
Since we started with a counter example let's continue with that and write
some code that actually implements it:
Copy
1module COUNTER #(
2pWIDTH=8
3) (
4input iCLK,
5input iRESET,
7);
9begin
11oCOUNTER<=0;
13oCOUNTER<= oCOUNTER+1;
14end
15end
16endmodule
The code above is pretty self explanatory... at every positive clock edge, if
we see input iRESET high we reset the counter, otherwise we increment it
by one... note that having a reset signal restoring our block to a known
state is often useful but not always necessary.
<=
assignment which is "registered" which means that the assignment will be kept for
as long as the next clock cycle.
Another way we could do this is removing the reg statement in the module
declaration and define the counter as follows:
Copy
1module COUNTER #(
2pWIDTH=8
3) (
4input iCLK,
5input iRESET,
7);
10begin
12rCOUNTER<=0;
15end
16end
17assign oCOUNTER=rCOUNTER;
18endmodule
This is basically the same stuff but we defined a register, worked on it and
then assigned with the "continuous"
=
assignment it to the output signal. The differsence here is that while
<=
means the signal changes only at clock edges
=
assigns the value continuously so the signal will eventually change at any time,
however if we assign it as we are doing in the example to a register that changes
only on clock edges the resulting signal is basically just an alias.
Copy
1module COUNTER #(
2pWIDTH=8
3) (
4input iCLK,
5input iRESET,
6output [pWIDTH-1:0] oCOUNTER
7);
13begin
15rCOUNTER<=0;
17rCOUNTER<= wNEXT_COUNTER;
18end
19end
20endmodule
We're basically still doing the same stuff but we have done it in a way that
makes it a bit more clear logically. Basically we are assigning continuously
the signal wNEXT_COUNTER to the value of the rCOUNTER plus one. This
means that wNEXT_COUNTER will (almost) immediately change as soon as
rCOUNTER changes value however rCOUNTER will be updated only on the
next positive clock edge (as it has a
<=
assignment) so the result is still that rCOUNTER changes only on clock edge.
Copy
3begin
5rCOUNT_UP<=0;
6rCOUNT_DOWN<=0;
8rCOUNT_UP<= rCOUNT_UP+1;
9rCOUNT_DOWN<= rCOUNT_DOWN-1;
10end
11end
Copy
1module PULSE_GEN #(
2pWIDTH=8,
3pHIGH_COUNT=240,
4pLOW_COUNT=40
5) (
6input iCLK,
7input iRESET,
8input iPULSE_REQ,
10);
13eST_IDLE,
14eST_PULSE_HIGH,
15eST_PULSE_LOW
16} rSTATE;
18begin
20rSTATE<=eST_IDLE;
21end else begin
22case (rSTATE)
23eST_IDLE: begin
25rSTATE<= eST_PULSE_HIGH;
26oPULSE<= 1;
28end
29end
30eST_PULSE_HIGH: begin
31rCOUNTER<= rCOUNTER-1;
33rSTATE<= eST_PULSE_LOW;
34oPULSE<= 0;
35rCOUNTER<= pLOW_COUNT-1;
36end
37end
38eST_PULSE_LOW: begin
39rCOUNTER<= rCOUNTER-1;
41rSTATE<= eST_IDLE;
42end
43end
44endcase
45end
46end
47endmodule
Here we see a number of new things we need to talk about. First of all we
are defining the rSTATE variable using enum. This helps in assigning the
state to easily understandable values rather than hard-coded numbers and
has the advantage that you can insert states easily without the need to
rewrite all your state machine.
Note that since oPULSE is registered it will retain its state until it's assigned
again. In the next state things get a bit more complicated... at each clock
we decrement the counter, then if counter reaches 0 we also change state,
change oPULSE to 0 AND we assign rCOUNTER again. Since the two
assignments are executed in parallel we need to know what this means and
lucky enough all HDL mandate that if two parallel statements are executed
on the same register only the last one will be really executed so the
meaning of what we just wrote is that normally we decrement the counter
but when counter reaches 0 we change state and re-initialize it to
pLOW_COUNT.
Copy
1module PWM #(
2parameter pCHANNELS=16,
3parameter pPRESCALER_BITS=32,
4parameter pMATCH_BITS=32
5)
6(
7input iCLK,
8input iRESET,
11input iWRITE,
13);
21reg rTICK;
22integer i;
24begin
29// even registers >=2: value at which PWM output is set high
30// odd registers >=2: value at which PWM output is set low
37endcase
38else begin
40case (iADDRESS[0])
410: rPRESCALER_MAX<=iWRITE_DATA;
421: rPERIOD_MAX<=iWRITE_DATA;
43endcase
44end
45end
47rPRESCALER_CNT<=rPRESCALER_CNT+1;
48rTICK<=0;
52// note that tick lasts only one clock cycle as it is reset by the rTICK<= 0
above
53rPRESCALER_CNT<=0;
54rTICK <=1;
55end
59rPERIOD_CNT<=rPERIOD_CNT+1;
61// and of course we reset the counter when we reach the max period.
62rPERIOD_CNT<=0;
63end
64end
65// this block implements the parallel comparators that actually generate
the PWM outputs
66// the for loop actually generates an array of logic that compares the
counter with
67// the high and low match values for each channel and set the output
accordingly.
69if (rMATCH_H[i]==rPERIOD_CNT)
70oPWM[i] <=1;
71if (rMATCH_L[i]==rPERIOD_CNT)
72oPWM[i] <=0;
73end
74end
75endmodule
There are a number of new things here to learn so let's start from the
module declaration. Here we are using a built in function to establish the
required bit width of the address bus. The purpose is to limit the address
span to the minimum required for the registers so for example if we want
10 channels we need a total of 22 addresses. Since each address bit
doubles the number of addresses we can use we need a total of 5 bits
which result in 32 total addresses. In order to make this parametric we
define iADDRESS width as $clog2(2*pCHANNELS+2) and we define registers
as a 2 dimensional array.
Actually there are two ways to make a multidimensional array and here we
are using the "unpacked" one, which basically defines the registers as
separate entities by adding indices on the left side of the register
declaration. The other way, we are not using in this example is the
"packed" one in which indices are both on the left side of the declaration
and the result is that the 2D array can also be seen as a single big register
containing the concatenation of all the registers.
Another interesting trick here is how we define the logic that handles
registers. First of all we are just implementing write only registers so you
won't find the iREAD and iREAD_DATA signals Secondly we wanted to have
a parametric register set where only the first two registers are always
present whereas the rest are dynamically defined and handled based on the
number of channels we want to implement. In order to do so we note that in
a binary number the least significant bit defines whether the number is odd
or even. Since we have two registers per channel this comes handy as we
can differentiate our behaviour depending on whether we are below
address 2 or not.
If we are below address 2 we implement the common registers which are
the prescaler count and the counter period. If we are above 2 we use the
LSB to decide if we are writing the value for the high or low comparator.
Another interesting thing we're doing here is that we are using continuous
assignment to determine a strobe and a direction from the quadrature
signals out of the encoder. In the code there are simple graphs showing
how the waveforms look like, although in order to fully understand how the
waveforms come out you have to consider that the equations use signals at
different points in time. This is done by simply using the shift register used
to synchronize asynchronous inputs also to delay them so tapping into a
different point of the shift register we can see how signal was the clock
before. In particular, if we move towards the input of the shift register we
get "newer" data whereas if we move towards the end we get "older" data.
If we look at the equations we see we are using the ^ operator which is a
logical exclusive or (XOR) which returns 1 if the two operands are different
and 0 otherwise.
One thing that may not look obvious at first look is that the equations are
parallelly calculating the same logic for all the inputs, in fact the
rRESYNC_ENCODER registers are packed bidimensional arrays arranged so
that the first index identifies the tap of the shift register and the second
index is the encoder channel. This means that whenever we reference
rRESYNC_ENCODER with a specific index we are selecting a mono-
dimensional array containing all the encoder inputs at once delayed by the
amount of clocks specified by the index. This also means that when we
perform a bitwise logic operation on an array we are actually instantiating
multiple parallel logic equations at the same time. Note that this can be
done only because the array is "packed" as with "unpacked" arrays
elements are considered separate and can't take part in equations this way
and they have to be addressed singularly.
As we did for the other examples the block implements multiple inputs and
does this by using a for loop that checks for the enable signal (which again
is an array as wide as the number of channels) and when that is high it
checks for the direction and based on that either increments or decrements
the counter for that channel. This is easily done using the ? : operator
(conditional expression) which works exactly like in C.
Finally the bus interface is pretty simple because the only registers we have
are the read only counters and we can implement this simply by checking
the read signal and assigning output data with the array of counters
indexed by the address, pretty much like it was a RAM.
Copy
1module QUAD_ENCODER #(
2pENCODERS=2,
3pENCODER_PRECISION=32
4)(
5input iCLK,
6input iRESET,
9input iAVL_READ,
14);
16// the first two delay taps are used to synchronize inputs with the internal
clocks
17// while the other two are used to compare two points in time of those
signals.
22// A __----____----__
23// B ____----____----
26//
28// A ____----____----
29// B __----____----__
34integer i;
37begin
39rSTEPS<=0;
40rRESYNC_ENCODER_A<=0;
41rRESYNC_ENCODER_B<=0;
42end
43else begin
44// implement shift registers for each channel. since arrays are packed we
can treat that as a monodimensional array
45// and by adding inputs at the bottom we are effectively shifting data by
one bit
46rRESYNC_ENCODER_A<={rRESYNC_ENCODER_A,iENCODER_A};
47rRESYNC_ENCODER_B<={rRESYNC_ENCODER_B,iENCODER_B};
48for (i=0;i<pENCODERS;i=i+1)
49begin
51if (wENABLE[i])
54end
56if (iAVL_READ)
57begin
59oAVL_READ_DATA<= rSTEPS[iAVL_ADDRESS];
60end
61end
62end
63endmodule
Last revision10/28/2024
What is Memory?
Memory blocks are essential parts of modern embedded systems,
especially microcontroller-based ones. Memory blocks are
semiconductor devices that store and retrieve information or data;
a microcontroller central processing unit (CPU) uses and processes data
stored in memory blocks to perform specific tasks.
Both are accessed by the CPU using the same communications bus, as
shown below. Von Neumann's architecture is fundamental since nearly all
digital computers design have been based on this architecture.
Harvard Architecture
The Harvard architecture, named after the Harvard Mark I relay-based
computer, was first introduced in the mid '40s. This architecture's main
characteristic is that it uses two separate memory units, one for storing
program instructions and one for storing program data. Both memory units
in the Harvard architecture are accessed by the CPU using different
communication buses.
Harvard architecture.
Microcontrol Architectur
Board Family
ler e
ATSAMD21G1 Von
Zero Arm® Cortex®-M0+
8 Neumann
Arm® Cortex®-
Portenta H7 STM32H747 Harvard
M4/M7
ATSAMD21G1 Von
MKR FOX 1200 Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR NB 1500 Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR Vidor 4000 Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR WiFi 1010 Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR Zero Arm® Cortex®-M0+
8 Neumann
ATSAMW25H1 Von
MKR1000 WIFI Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR WAN 1300 Arm® Cortex®-M0+
8 Neumann
ATSAMD21G1 Von
MKR WAN 1310 Arm® Cortex®-M0+
8 Neumann
Microcontrol Architectur
Board Family
ler e
ATSAMD21G1 Von
Nano 33 IoT Arm® Cortex®-M0+
8 Neumann
Memory Types
All the different memory units inside a microcontroller can be divided into
two main types: RAM and ROM. RAM (from Random-Access Memory) in
microcontroller-based systems is a volatile memory used to store
temporary data such as the system's firmware variables. ROM (from Read-
Only Memory) in microcontroller-based systems is non-volatile memory
used to store permanent data such as the system's firmware.
Flash
RAM
EEPROM
Flash
Flash memory in microcontroller-based systems is part of its ROM. The
flash memory is where the system's firmware is stored to be executed. For
example, think of the famous
Blink.ino
sketch: when we compile this sketch, we create a binary file that is later stored in
the flash memory of an Arduino board. The sketch is then executed when the board
is powered on.
RAM
RAM in microcontroller-based systems is where the system's temporary
data or run-time data is stored; for example, the variables created by
functions of a program. RAM in microcontrollers usually is SRAM; this is a
type of RAM that uses a flip-flop to store one bit of data. There is also
another type of RAM that can be found in microcontrollers: DRAM.
EEPROM
In microcontroller-based systems, Erasable Programmable Read-Only
Memory, or EEPROM, is also part of its ROM; actually, Flash memory is a
type of EEPROM. The main difference between Flash memory and EEPROM
is how they are managed; EEPROM can be managed at the byte level (write
or erased) while Flash can be managed at the block level.
Text
Data
BSS
Stack
Heap
The
text
section contains instructions loaded into the flash memory;
data
section contains variables initialized in the sketch,
BSS
section contains uninitialized data,
stack
section stores data of functions and interrupts, and
heap
section stores variables created during run time.
In hybrid ARM architectures, a so called memory map is implemented,
with a different address map configuration of 32-bit, 36-bit, and 40-bit that
depends on the requirement of System On a Chip (SoC) address space with
extra DRAM. The Memory Map grants interface with SoC design, while
having most system control on a high level coding. Memory access
instructions can be used on high level code to manage interrupt modules
and built-in peripherals. All of this controlled by Memory Management
Unit (MMU).
The memory resource is handled by the MMU. The main role of the MMU is
to enable the processor to run multiple tasks independently in its own
virtual memory space; the MMU then uses translation tables to establish a
bridge between the virtual and the physical memory addresses. Virtual
Address is managed via software with memory instructions, and Physical
address is the memory system that is controlled depending on the
Translation Table input given by the Virtual Address.
Virtual address:
o Kernel code and data
o Application code and data
Physical address:
o ROM
o RAM
o Flash
o Peripherals
UNO WiFi
ATmega4809 AVR Harvard 48kB 6kB 256B
Rev2
UNO Rev3
ATmega328P AVR Harvard 32kB 2kB 1kB
SMD
Arm®
ATSAMD21G1 Von 256k
Zero Cortex® 32kB -
8 Neumann B
-M0+
Portenta H7
Arm®
(basic
STM32H747 Cortex® Harvard 16MB 8MB -
configuration
-M4/M7
)
Arm®
Nicla Sense 512k
nRF52832 Cortex® Harvard 64kB -
ME B
-M4
Microcontrol Architect Flas SRA EEPRO
Board Family
ler ure h M M
Arm®
Nano RP2040 Von 264k
RP2040 Cortex® - -
Connect Neumann B
-M0+
Arm®
MKR FOX ATSAMD21G1 Von 256k
Cortex® 32kB -
1200 8 Neumann B
-M0+
Arm®
ATSAMD21G1 Von 256k
MKR NB 1500 Cortex® 32kB -
8 Neumann B
-M0+
Arm®
MKR Vidor ATSAMD21G1 Von 256k
Cortex® 32kB -
4000 8 Neumann B
-M0+
Arm®
MKR WiFi ATSAMD21G1 Von 256k
Cortex® 32kB -
1010 8 Neumann B
-M0+
Arm®
ATSAMD21G1 Von 256k
MKR Zero Cortex® 32kB -
8 Neumann B
-M0+
Arm®
MKR1000 ATSAMW25H1 Von 256k
Cortex® 32kB -
WIFI 8 Neumann B
-M0+
Microcontrol Architect Flas SRA EEPRO
Board Family
ler ure h M M
Arm®
MKR WAN ATSAMD21G1 Von 256k
Cortex® 32kB -
1300 8 Neumann B
-M0+
Arm®
MKR WAN ATSAMD21G1 Von 256k
Cortex® 32kB -
1310 8 Neumann B
-M0+
Arm®
ATSAMD21G1 Von 256k
Nano 33 IoT Cortex® 32kB -
8 Neumann B
-M0+
Arm®
256k
Nano 33 BLE nRF52840 Cortex® Harvard 1MB -
B
-M4
Arm®
Nano 33 BLE 256k
nRF52840 Cortex® Harvard 1MB -
Sense B
-M4
Pro hardware SDRAM and Flash memory are highly customizable in volumes. Check
out the Pro site for more information.
Measuring Memory Usage in Arduino® Boards
Memory usage statistics help comprehend the insight of resource
management affected by the designed code structure. Memory load
demand is one statistic that will give you an insight into how efficient the
code is designed. It is a crucial development consideration element because
the resources are finite inside a microcontroller-based system; software
should always perform without reaching maximum load capacity to
avoid problems or issues. Memory load could be observed either
as available RAM at disposal for specific tasks or flash storage
remaining capacity for required headroom.
The IDE's compiler output console log for an ARM-based Arduino® board,
the MKR WAN 1310, is shown in the image below:
Flash memory memory measurement in an ARM-based Arduino® board
The IDE's compiler output console log for another ARM-based Arduino®, the
Portenta H7, is shown in the image below:
Flash memory memory measurement in an ARM-based Arduino® board
Notice that the compiler's output changes depending on if the board is AVR-
based or ARM-based.
Copy
1void display_freeram() {
3 Serial.println(freeRam());
4}
6int freeRam() {
8 int v;
11}
heap
section is where variables created during the run time are stored. In the code,
__heap_start
and
__brkval
are as following:
__heap_start
heap
section.
__brkval
heap
Copy
3void display_freeram(){
5 Serial.println(freeRam());
6}
8int freeRam() {
9 char top;
11}
EEPROM
library can be used to read, write and erase the EEPROM memory. The following
code shows how a byte of information can be stored in the EEPROM memory and
then read using the
write
and
read
functions:
Copy
1#include <EEPROM.h>
3void setup() {
4}
5
6void loop {
8 EEPROM.write(address, value);
11 EEPROM.read(address);
12}
Copy
1#include <EEPROM.h>
3void setup() {
4}
6void loop {
9 EEPROM.write(i, 0);
10
11}
For more information on how to manage the EEPROM memory, you can refer to this
guide.
Optimizing Memory Usage in Arduino-based
Systems
Knowing how code uses memory resources of a system is just the first
recommended task in the development process; a whole different task
is optimizing memory usage. As the term development may infer, the
requirements may change or be adjusted depending on external factors
such as reduced device capacity due to the unavailability of the
components. Thus the code architecture may require optimization to run on
the reduced limited memory resources.
Modular tasks mean functions that wrap code that will be used
repetitively or continuously by receiving different parameters. It is a
great way to maintain clean code structure and performance while reducing
the memory space required for additional tasks that might need to be
implemented.
The ideal way to use the Print Line command is to use the
F()
String Wrapper around the literals. See the example below:
String Wrapper
Serial.print()
or
Serial.println()
instructions uses SRAM space, which can be convenient but not desirable. The ideal
way to use a
Serial.print()
or
Serial.println()
instruction is with the use of the
F()
String wrapper around the literals. For example:
Copy
1Serial.println(F("Something"));
Something
with the
F()
wrapper will move the Strings to Flash memory only rather than to use
SRAM space also. Using the
F()
wrapper can be observed as offloading such data to Flash memory instead of
SRAM. Flash memory is much more spacious than SRAM, so it is better to use Flash
memory space than SRAM, which will use
heap
section. This does not mean that memory space will always be available, as Flash
memory does have limited space. It is not recommended to clog code with
Serial.print()
or
Serial.println()
instructions, but use them where they most matter inside the code.
PROGMEM
Not only Strings occupy SRAM space, but global variables also take up
quite a good amount of SRAM space. As global and static variables are
streamed into SRAM space and push the
heap
memory section towards the
stack
. The space occupied by these variables streamed into SRAM space will be saved at
its location and will not be changing, meaning more of these variables are created,
they will use more space, and consequently, the system presenting problems and
issues due to poor memory management.
PROGMEM
, which stands for Program Memory, can be used to store variable data into Flash
memory space, just as the
F()
wrapper described before, but the use of
PROGMEM
presents one disadvantage: data read speed. Using RAM will provide a much faster
data read speed, but
PROGMEM
, as it uses Flash memory, will be slower than RAM, given the same data size. Thus,
it is essential to design code knowing which variables are crucial and which do not
or have a lower priority.
The use of
PROGMEM
in an AVR-based Arduino® board is shown in the example code below:
Copy
1#include <avr/pgmspace.h>
You can read more about PROGMEM in the Arduino Language Reference .
static const
over the variables.
Copy
Namespace Level
o At Namespace level, we are pointing at the variables and it is differed
whether
static
Function Level
o If it is declared within
static
Class Level
o On a Class level,
static
declaration will mean any type of applicable data that is handled will
be shared in between the instances.
Reserve Function
In tasks in code work with Strings that change in size depending on the
operation outcome,
reserve()
is the way to go. This function will help reserve buffer space and pre-allocate
for a String variable, changing its size and avoiding memory fragmentation. A
String variable that changes in its size could result from an int type variable
wrapped to be used as a String, for example.
reserve()
instruction:
Copy
3String_Variable.reserve(Alloc_Size);
reserve()
function, visit Arduino Language Reference .
HardwareSerial.h
file that can be found in the installation folder of the Arduino IDE:
Copy
1#define SERIAL_TX_BUFFER_SIZE 64
3#define SERIAL_RX_BUFFER_SIZE 64
External libraries can usually be modified to optimize buffer sizes used for performing
specific tasks of the libraries.
Data types exist to ease data stream format and to be handled without
making illegal access. The illegal access in terms of data types are meant
when the data is handled in the code with incompatible format. So it is a
good practice to not to abuse the the data type and use only convenient
types for every data bits. Rather, design and allocate memory carefully
according to the requirements, which will help to reserve some memory
space if further designed tasks needs extra space.
The following table shows basic value data types in Arduino:
Byte
Type Range of Values
Length
unsigned
1 0 to 255
char
byte 1 0 to 255
word 2 0 to 65,535
-2,147,483,648 to
long 4
2,147,483,647
unsigned
4 0 to 4,294,967,295
long
-3.4028235E+38 to
float 4
3.4028235E+38
-3.4028235E+38 to
double 4
3.4028235E+38
write
operation is limited. The
read
operation is unlimited for EEPROM; however, the
write
operation is finite and usually capped at 100,000 cycles. Thus, it is essential to
save only essential parameters for sensors or modules to work with primarily
unchanging data. Additionally, avoid implementing
write
operations into loops to avoid constant
write
operations, these operations should be minimized while the system is working.
As EEPROM is limited with the write operation cycle, it also applies to Flash
memory. Both of them are subjected to data retention loss after the
manufacturer's defined life cycle. EEPROM is based on NOR-type memory,
while the Flash memory is NAND type, making the EEPROM more costly
than Flash memory. EEPROM works by accessing the data byte-wise,
whereas Flash memory accesses block by block.
write
cycles. With two new additional functions stated in the library,
EEPROM.commit()
should not be called inside a loop function; otherwise, it will wipe out the Flash
memory's
write
operation cycles, thus losing data retention ability.
8-bit AVR® Core documentation in the Microchip® Developer help site . Here
you can find detailed information of the 8-bit AVR® Central Processing Unit
(CPU).
ARM architecture documentation site. Here you can find detailed information
of the different ARM processors. Check out the Cortex-M0+ and Cortex-M4
Technical Reference Manuals.
References
[1] S. F. Barrett and D. J. Pack, Microchip AVR® Microcontroller Primer:
Programming and Interfacing, Third Edition (Synthesis Lectures on Digital
Circuits and Systems), Morgan & Claypool, 2019.
[2] J. Y. Yiu, The Definitive Guide to Arm® Cortex®-M0 and Cortex-M0+
Processors, Second ed., Newnes, 2015.
A guide to EEPROM
Learn how to use EEPROM, short for electrically erasable programmable read-only
memory, on Arduino boards.
Last revision10/28/2024
Hardware Required
All of the following boards have an EEPROM:
EEPROM Clear
This example illustrates how to set of all of those bytes to 0, initializing
them to hold new information, using the EEPROM.write() function.
Copy
1/*
2 * EEPROM Clear
3*
4 * Sets all of the bytes of the EEPROM to 0.
7*
9 */
10
11#include <EEPROM.h>
12
13void setup() {
15 pinMode(13, OUTPUT);
16
17 /***
23 Rather than hard-coding the length, you should use the pre-provided
length function.
25 ***/
26
29 }
30
32 digitalWrite(13, HIGH);
33}
34
35void loop() {
37}
EEPROM CRC
A CRC is a simple way of checking whether data has changed or become
corrupted. This example calculates a CRC value directly on the EEPROM
values. This CRC is like a signature and any change in the calculated CRC
means a change in the stored data. The purpose of this example is to
highlight how the EEPROM object can be used just like an array.
Copy
1/***
10
11 The purpose of this example is to highlight how the EEPROM object can
be used just like an array.
12
13***/
14
15#include <Arduino.h>
16#include <EEPROM.h>
17
18void setup() {
19
20 //Start serial
21
22 Serial.begin(9600);
23
24 while (!Serial) {
25
26 ; // wait for serial port to connect. Needed for native USB port only
27
28 }
29
31
32 Serial.print("EEPROM length: ");
33
34 Serial.println(EEPROM.length());
35
37
39
40 Serial.println(eeprom_crc(), HEX);
41
42 Serial.print("\n\nDone!");
43}
44
45void loop() {
46
47 /* Empty loop */
48}
49
51
53
55
59
61
62 };
63
65
67
69
70 crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
71
72 crc = ~crc;
73
74 }
75
76 return crc;
77}
EEPROM Get
The purpose of this example is to show how the put and get methods
provide a different behaviour than write and read, that work on single
bytes. Getting different variables from EEPROM retrieve a number of bytes
that is related to the variable datatype.
Copy
1/***
3 eeprom_get example.
9 This sketch will run without it, however, the values shown
10
12
13 This may cause the serial object to print out a large string
14
16
17 loaded.
18
20
22
23***/
24
25#include <EEPROM.h>
26
27void setup() {
28
30
32
33 Serial.begin(9600);
34
35 while (!Serial) {
36
37 ; // wait for serial port to connect. Needed for native USB port only
38
39 }
40
42
44
45 EEPROM.get(eeAddress, f);
46
47 Serial.println(f, 3); //This may print 'ovf, nan' if the data inside the
EEPROM is not a valid float.
48
49 /***
50
52
54
55 ***/
56
57 /***
58
60
62
63 ***/
64
66}
67
68struct MyObject {
69
70 float field1;
71
72 byte field2;
73
74 char name[10];
75};
76
77void secondTest() {
78
79 int eeAddress = sizeof(float); //Move address to the next byte after float
'f'.
80
82
83 EEPROM.get(eeAddress, customVar);
84
86
87 Serial.println(customVar.field1);
88
89 Serial.println(customVar.field2);
90
91 Serial.println(customVar.name);
92}
93
94void loop() {
95
96 /* Empty loop */
97}
EEPROM Iteration
The purpose of this example is to show how to go through the whole
EEPROM memory space with different approaches. The code provided
doesn't run on its own but should be used as a source of code snippets to
be used elsewhere.
Copy
1/***
3 eeprom_iteration example.
10
12
14
17***/
18
19#include <EEPROM.h>
20
21void setup() {
22
23 /***
24
26
27 ***/
28
30
32
33 EEPROM[ index ] += 1;
34
35 }
36
37 /***
38
40
41 ***/
42
43 int index = 0;
44
46
48
49 EEPROM[ index ] += 1;
50
51 index++;
52
53 }
54
55 /***
56
58
59 ***/
60
61 int idx = 0; //Used 'idx' to avoid name conflict with 'index' above.
62
63 do {
64
67 EEPROM[ idx ] += 1;
68
69 idx++;
70
72
74
75void loop() {}
EEPROM Put
The purpose of this example is to show the
EEPROM.put()
method that writes data on EEPROM using also the EEPROM.update() that
writes data only if it is different from the previous content of the locations to
be written. The number of bytes written is related to the datatype or custom
structure of the variable to be written.
Copy
1/***
3 eeprom_put example.
7 Also, this sketch will pre-set the EEPROM data for the
8
9 example sketch eeprom_get.
10
12
14
16
17 different.
18
20
22
23***/
24
25#include <EEPROM.h>
26
27struct MyObject {
28
29 float field1;
30
31 byte field2;
32
33 char name[10];
34};
35
36void setup() {
37
38 Serial.begin(9600);
39
40 while (!Serial) {
41
42 ; // wait for serial port to connect. Needed for native USB port only
43
44 }
45
47
49
50 //One simple call, with the address first and the object second.
51
52 EEPROM.put(eeAddress, f);
53
55
56 /** Put is designed for use with custom structures also. **/
57
58 //Data to store.
59
60 MyObject customVar = {
61
62 3.14f,
63
64 65,
65
66 "Working!"
67
68 };
69
70 eeAddress += sizeof(float); //Move address to the next byte after float 'f'.
71
72 EEPROM.put(eeAddress, customVar);
73
75}
76
77void loop() {
78
79 /* Empty loop */
80}
EEPROM Read
This example illustrates how to read the value of each byte EEPROM using
the
EEPROM.read()
function, and how to print those values to the serial window of the Arduino
Software (IDE).
Copy
1/*
2 * EEPROM Read
3*
5 * to the computer.
7 */
9#include <EEPROM.h>
10
11// start reading from the first byte (address 0) of the EEPROM
12int address = 0;
13byte value;
14
15void setup() {
17 Serial.begin(9600);
18 while (!Serial) {
19 ; // wait for serial port to connect. Needed for native USB port only
20 }
21}
22
23void loop() {
25 value = EEPROM.read(address);
26
27 Serial.print(address);
28 Serial.print("\t");
29 Serial.print(value, DEC);
30 Serial.println();
31
32 /***
33 Advance to the next address, when at the end restart at the beginning.
34
39
40 Rather than hard-coding the length, you should use the pre-provided
length function.
42 ***/
43 address = address + 1;
44 if (address == EEPROM.length()) {
45 address = 0;
46 }
47
48 /***
51
53 ***/
54
55 delay(500);
56}
EEPROM Update
The purpose of this example is to show the
EEPROM.update()
method that writes data only if it is different from the previous content of
the locations to be written. This solution may save execution time because
every write operation takes 3.3 ms; the EEPROM has also a limit of 100,000
write cycles per single location, therefore avoiding rewriting the same value
in any location will increase the EEPROM overall life.
Copy
1/***
10
12 ***/
13
14#include <EEPROM.h>
15
16/** the current address in the EEPROM (i.e. which byte we're going to write
to next) **/
17int address = 0;
18
19void setup() {
21}
22
23void loop() {
24 /***
28 ***/
31 /***
34 turned off.
35 ***/
36 EEPROM.update(address, val);
37
38 /***
40
42 EEPROM.write(address, val);
43 }
44 ***/
45
46
47 /***
48 Advance to the next address, when at the end restart at the beginning.
49
55 Rather than hard-coding the length, you should use the pre-provided
length function.
57 ***/
58 address = address + 1;
59 if (address == EEPROM.length()) {
60 address = 0;
61 }
62
63 /***
66
68 ***/
69
70 delay(100);
71}
EEPROM Write
This example illustrates how to store values read from analog input 0 into
the EEPROM using the
EEPROM.write()
function. These values will stay in the EEPROM when the board is turned off
and may be retrieved later by another sketch.
Copy
1/*
3 * EEPROM Write
5*
10
12
13 */
14
15#include <EEPROM.h>
16
17/** the current address in the EEPROM (i.e. which byte we're going to write
to next) **/
18int addr = 0;
19
20void setup() {
21
23}
24
25void loop() {
26
27 /***
28
30
AuthorArduino
Last revision10/28/2024
This guide collects compatible hardware and great code examples that you
can use if you want to get started with Secure Digital (SD) cards.
The examples in this guide comes from the SD Library, which originally is based
on SdFat by William Greiman.
MKR Zero
MKR IoT Carrier
MKR MEM Shield
MKR SD Proto Shield
MKR ENV Shield
MKR Ethernet Shield
Arduino Education Shield
Circuit
Here is an example of how to insert an SD card into the MKR Zero board.
None of the examples below requires any additional circuit.
Examples
Below are a series of examples
setup()
SD.open()
named "test.txt".
FILE_WRITE
enables read and write access to the file, starting at the end. If a file
"test.txt"
myFile.println()
to write a string to the card, followed by a carriage return. Once the content
is written, close the file.
SD.open()
. Once opened, ask the Arduino to read the contents of the file with
SD.read()
and send them over the serial port. After all the contents of the file are read,
close the file with
SD.close()
Note that pin 4 is default Chip Select (CS) pin for most boards. To set CS for MKR Zero,
you can use 28 instead of 4, alt. use the SDCARD_SS_PIN definition.
Copy
1/*
2 SD card read/write
4 This example shows how to read and write data to and from an SD card
file
5 The circuit:
7 ** MOSI - pin 11
8 ** MISO - pin 12
9 ** CLK - pin 13
11
13 by David A. Mellis
15 by Tom Igoe
16
18
19*/
20
21#include <SPI.h>
22#include <SD.h>
23
24File myFile;
25
26void setup() {
28 Serial.begin(9600);
29 while (!Serial) {
30 ; // wait for serial port to connect. Needed for native USB port only
31 }
32
33
34 Serial.print("Initializing SD card...");
35
36 if (!SD.begin(4)) {
37 Serial.println("initialization failed!");
38 while (1);
39 }
40 Serial.println("initialization done.");
41
42 // open the file. note that only one file can be open at a time,
45
47 if (myFile) {
48 Serial.print("Writing to test.txt...");
49 myFile.println("testing 1, 2, 3.");
52 Serial.println("done.");
53 } else {
56 }
57
59 myFile = SD.open("test.txt");
60 if (myFile) {
61 Serial.println("test.txt:");
62
64 while (myFile.available()) {
65 Serial.write(myFile.read());
66 }
68 myFile.close();
69 } else {
72 }
73}
74
75void loop() {
76 // nothing happens after setup
77}
Card Information
This example shows how to read information about a SD card. The example
reports volume type, free space and other information using the SD library,
sending it over the serial port.
Copy
1/*
3 SD card test
5 This example shows how use the utility libraries on which the'
9 Very useful for testing a card when you're not sure whether its working or
not.
10
11 Pin numbers reflect the default SPI pins for Uno and Nano models
12
13 The circuit:
14
16
18
19 ** SDI - pin 12 on Arduino Uno/Duemilanove/Diecimila
20
22
24
26
28
29 by Limor Fried
30
32
33 by Tom Igoe
34
35*/
37#include <SPI.h>
38#include <SD.h>
39
41
42Sd2Card card;
43
44SdVolume volume;
45
46SdFile root;
47
54
56
57void setup() {
58
60
61 Serial.begin(9600);
62
63 while (!Serial) {
64
65 ; // wait for serial port to connect. Needed for native USB port only
66
67 }
68
69 Serial.print("\nInitializing SD card...");
70
72
74
75 if (!card.init(SPI_HALF_SPEED, chipSelect)) {
76
78
80
82
83 Serial.println("* did you change the chipSelect pin to match your shield
or module?");
84
85 while (1);
86
87 } else {
88
90
91 }
92
93 // print the type of card
94
95 Serial.println();
96
98
99 switch (card.type()) {
100
102
103 Serial.println("SD1");
104
105 break;
106
108
109 Serial.println("SD2");
110
111 break;
112
114
115 Serial.println("SDHC");
116
117 break;
118
119 default:
120
121 Serial.println("Unknown");
122
123 }
124
126
127 if (!volume.init(card)) {
128
130
132
133 }
134
136
137 Serial.println(volume.clusterCount());
138
140
141 Serial.println(volume.blocksPerCluster());
142
144
146
147 Serial.println();
148
149 // print the type and size of the first FAT-type volume
150
152
154
156
158
160
162
164
165 Serial.println(volumesize);
166
168
170
171 Serial.println(volumesize);
172
174
176
177 Serial.println("\nFiles found on the card (name, date and size in bytes):
");
178
179 root.openRoot(volume);
180
181 // list all files in the card with date and size
182
184
185 root.close();
186}
187
188void loop(void) {
189}
Please note: the cluster size is defined at format time by the user and has some
default values that can be changed by users following some rules. In the sketch above
we are using the default size for a block that is set at 512 bytes by standards. This
value is not the cluster size: that is calculated as the number of blocks per cluster. You
may find more in depth information about cluster sizes in this article.
Dump File
This example shows how to read a file from a SD card using the SD library
and send it over the serial port.
loop()
, the file is opened when calling
SD.open()
. To send the file serially to a computer, use
Serial.print()
, reading the contents of the file with
SD.read()
.
Copy
1/*
5 This example shows how to read a file from the SD card using the
9 Pin numbers reflect the default SPI pins for Uno and Nano models.
10
11 The circuit:
12
14
15 ** SDO - pin 11
16
17 ** SDI - pin 12
18
19 ** CLK - pin 13
20
22
24
26
28
29 by Limor Fried
30
32
33 by Tom Igoe
34
37*/
38#include <SD.h>
39
41
42void setup() {
43
45
46 Serial.begin(9600);
47
48 // wait for Serial Monitor to connect. Needed for native USB port boards
only:
49
50 while (!Serial);
51
52 Serial.print("Initializing SD card...");
53
54 if (!SD.begin(chipSelect)) {
55
57
59
60 Serial.println("2. is your wiring correct?");
61
62 Serial.println("3. did you change the chipSelect pin to match your shield
or module?");
63
65
66 while (true);
67
68 }
69
70 Serial.println("initialization done.");
71
72 // open the file. note that only one file can be open at a time,
73
75
77
79
80 if (dataFile) {
81
82 while (dataFile.available()) {
83
84 Serial.write(dataFile.read());
85
86 }
87
88 dataFile.close();
89
90 }
91
93
94 else {
95
97
98 }
99}
100
101void loop() {
102}
File Management
This example shows how to create and destroy a file on a SD card.
In the
setup()
, open a new file with
SD.open()
named "example.txt".
FILE_WRITE
enables read and write access to the file, starting at the end. In this example
though, immediately close the file by calling
myFile.close()
.
SD.exists()
, delete the file from the card with
SD.remove
.
Copy
1/*
10
12
13 ** SDO - pin 11
14
15 ** SDI - pin 12
16
17 ** CLK - pin 13
18
20
22
24
26
27 by David A. Mellis
28
30
31 by Tom Igoe
32
34
35*/
36#include <SD.h>
37
39
40File myFile;
41
42void setup() {
43
45
46 Serial.begin(9600);
47
48 // wait for Serial Monitor to connect. Needed for native USB port boards
only:
49while (!Serial);
50
51 Serial.print("Initializing SD card...");
52
53 if (!SD.begin(10)) {
54
55 Serial.println("initialization failed!");
56
57 while (1);
58
59 }
60
61 Serial.println("initialization done.");
62
63 if (SD.exists("example.txt")) {
64
65 Serial.println("example.txt exists.");
66
67 } else {
68
70
71 }
72
74
75 Serial.println("Creating example.txt...");
76
78
79 myFile.close();
80
82
83 if (SD.exists("example.txt")) {
84
85 Serial.println("example.txt exists.");
86
87 } else {
88
90
91 }
92
94
95 Serial.println("Removing example.txt...");
96
97 SD.remove("example.txt");
98
99 if (SD.exists("example.txt")) {
100
102
103 } else {
104
106
107 }
108}
109
110void loop() {
111
113}
List Files
This example shows how to list the files available in the directory of the SD
card.
The main
loop()
does nothing because the function that prints out the file directory of "/" of the SD
card is called from the
setup()
. This because we need to see it just once.
The
printDirectory
function scans through the list of entries and prints on serial every file and
directory present. For files the size is printed as well.
Copy
1/*
3 Listfiles
10
11 The circuit:
12
14
15 ** SDO - pin 11
16
17 ** SDI - pin 12
18
19 ** CLK - pin 13
20
22
24
26
28
29 by David A. Mellis
AuthorArduino
Last revision10/28/2024
Bit masks are used to access specific bits in a byte of data. This is often
useful as a method of iteration, for example when sending a byte of data
serially out a single pin. In this example the pin needs to change it's state
from high to low for each bit in the byte to be transmitted. This is
accomplished using what are known as bitwise operations and a bit mask.
Bitwise operations perform logical functions that take affect on the bit level.
Standard bitwise operations include AND (&) OR (|) Left Shift (
<<
) and Right Shift (
>>
).
The AND (&) operator will result in a 1 at each bit position where both input
values were 1. For example:
Copy
1x: 10001101
3 y: 01010111
5x & y: 00000101
The OR (|) operator (also known as Inclusive Or) will result in a 1 at each bit
position where either input values were 1. For example:
Copy
1x: 10001101
3 y: 01010111
5x | y: 11011111
<<
) operator will shift a value to the left the specified number of times. For example:
Copy
1y = 1010
3 x = y << 1
4
5yields: x = 10100
All the bits in the byte get shifted one position to the left and the bit on the
left end drops off.
The Right Shift (>>) operator works identically to left shift except that it
shifts the value to the right the specified number of times For example:
Copy
1y = 1010
3 x = y >> 1
5yields: x = 0101
All the bits in the byte get shifted one position to the right and the bit on
the right end drops off.
For a practical example, let's take the value 170, binary 10101010. To pulse
this value out of pin 7 the code might look as follows:
Copy
6void setup()
7{
9 pinMode(transmit,OUTPUT);
10}
11
12void loop()
13{
14
16
18
19 digitalWrite(transmit,HIGH); // send 1
20
21 }
22
24
25 digitalWrite(transmit,LOW); // send 0
26
27 }
28
29 delayMicroseconds(bitDelay); //delay
30
31 }
32}
Here we use a FOR loop to iterate through a bit mask value, shifting the
value one position left each time through the loop. In this example we use
the
<<=
operator which is exactly like the
<<
operator except that it compacts the statement
Copy
100000001
2& 10101010
4 ________
6 00000000
And our output pin gets set to 0. Second time through the loop the mask =
00000010, so our operation looks like:
Copy
100000010
2& 10101010
4 ________
6 00000010
And our output pin gets set to 1. The loop will continue to iterate through
each bit in the mask until the 1 gets shifted left off the end of the 8 bits and
our mask =0. Then all 8 bits have been sent and our loop exits.
Audio Basics with Arduino
Learn how to create tones and even entire songs using an Arduino.
Last revision10/28/2024
The examples are nevertheless still relevant as they explain some basic
concepts of generating tone frequencies, interpolation and even provide
you with some songs to try out. If you want to see an example for a simple
melody using the tone() library and familiarize yourself with the concept of
external sound data files, you can check out this example.
Most sketches in this article use pin 8 as output for the piezo buzzer or
speaker which means you only need to connect your components a shown
below and try out the different examples by uploading them to your
Arduino. Only the PCMAudio example uses pin 11 as it is making use
of PWM.
Hardware Required
Arduino board
piezo buzzer or a speaker
hook-up wires
Circuit
Schematic
Basics
Most times a piezo buzzer is used to produce sounds with an Arduino. When
voltage is applied to a piezoelectric ceramic material it causes it to vibrate
rapidly, resulting in the generation of sound waves. Every wave has an
associated property called frequency which measures how many cycles
happen every second. This unit of cycles is called Hertz (Hz). E.g., A middle
C on the piano has a frequency of 262 Hz which means that the air
oscillates back and forth 262 times every second.
Another property of a wave is its period, which equals to one divided by the
frequency, measuring the length and time of the wave. So, for that middle
C on the piano the cycle repeats every 3.8 milliseconds. While a normal
pure tone is a sine wave, it is much easier to create a square wave using an
Arduino by turning the pin on, waiting for a certain amount of time, then
turning the pin off and waiting again.
Freqout
The following example was created by Paul Badger in 2007. It shows a
simple tone generation function generating square waves of arbitrary
frequency and duration. The program also includes a top-octave lookup
table & transportation function.
Copy
4int ptime;
6int i, j;
10
11float noteval;
12
15float A = 14080;
16float AS = 14917.2;
17float B = 15804.3;
18float C = 16744;
19float CS = 17739.7;
20float D = 18794.5;
21float DS = 19912.1;
22float E = 21096.2;
23float F = 22350.6;
24float FS = 23679.6;
25float G = 25087.7;
26float GS = 26579.5;
27float A2 = 28160;
29float B2 = 31608.5;
30float C2 = 33488.1;
32float D2 = 37589.1;
34float E2 = 42192.3;
35float F2 = 44701.2;
37float G2 = 50175.4;
39float A3 = 56320;
40
42float oct8 = 4;
43float oct7 = 8;
44float oct6 = 16;
51
52//rhythm values
53int wh = 1024;
54int h = 512;
55int dq = 448;
56int q = 256;
57int qt = 170;
58int de = 192;
59int e = 128;
60int et = 85;
62int sx = 64;
64
66
67float majScale[] = {
68 A, B, CS, D, E, FS, GS, A2, B2, C2S, D2, E2, F2S, G2S, A3};
69
70void setup() {
71 Serial.begin(9600);
72}
73
74
75void loop(){
82
83 dur = 100;
84 freqout((int)noteval, dur);
85
86 delay(10);
87 }
88 }
89}
90
92{
93 int hperiod; //calculate 1/2 period in us
94 long cycles, i;
96
98
100 // Serial.print(freq);
102 // Serial.print(hperiod);
103 // Serial.print((char)9);
104 // Serial.println(cycles);
105
108 delayMicroseconds(hperiod);
111 }
113
114}
Duration extension
In the example below some minor tweaks have been made, mostly
changing the array to have durations and a sentinel was added to mark the
end. The example shown above remains as it shows a great simplistic
structure.
Copy
1float EIGHTH = 1;
2 float QUARTER = 2;
4 float HALF = 4;
8 float majScale[] = {
11 };
12
13 float odeToJoy[] = {
19 };
20
25 if(dur < 0) {
26 break;
27 freqout((int)noteval, dur);
28 delay(10);
29 }
30 }
31 }
Examples
Function Library
Smoothstep
This example is made by Dan Thompson in 2009 for smooth interpolation
between two values. Smoothstep is a common formula used for many
different applications such as Animation and Audio. This sketch includes a
Serial Printout to help you visualize the formula.
Visit danthompsonsblog.blogspot.com for the full smoothstep tutorial as
well as many others. For a comprehensive overview of interpolation as well
as some great Tips and Tricks visit this page.
Code
Copy
1///////////////////////////////////////
3///////////////////////////////////////
6//
8// https://sol.gfxile.net/interpolation/
9//
11//
12// This sketch was written with motion controlled timelapse photography
13// in mind. I have tried to make it generic enough to understand the
smoothstep
14// concept so that one might adapt this powerful formula in other areas as
well.
15//
17//
18// Usage:
20// 2. Click on the Serial monitor to see some visual feed back of the
SMOOTHSTEP function.
21// 3. Scroll through the print out to see the SMOOTHSTEP curve.
23
25
33
34void setup() {
37
38void loop()
39{
40if (j < N) // Keep looping until we hit the pre-defined max number
41// of steps
42{
46//smoothstep result.
47for ( i=0; i < X ; i++) // This loop could the relevant code for each time
your
48//motor steps.
49{
51 }
52Serial.print(" "); //Puts a space between each line of steps and their
56j++; // Increments j by 1.
57}
58}
PCMAudio
The following example was created by Michael Smith and is the precursor
for the PCM library created by David Mellis. It plays 8-bit PCM audio on pin
11 using pulse-width modulation (PWM). It uses two timers. The first
changes the sample value 8000 times a second. The second holds pin 11
high for 0-255 ticks out of a 256-tick cycle, depending on the sample value.
The second timer repeats 62500 times per second (16000000 / 256), which
is much faster than the playback rate (8000 Hz), so it almost sounds
halfway decent, just really quiet on a PC speaker.
Takes over Timer 1 (16-bit) for the 8000 Hz timer. This breaks PWM
(analogWrite()) for Arduino pins 9 & 10. It then takes Timer 2 (8-bit) for the
pulse width modulation, breaking the PWM for pins 11 & 13.
References:
http://tet.pub.ro/ (PDF).
https://www.evilmadscientist.com/article.php/avrdac
https://www.gamedev.net/reference/articles/article442.asp
Code
Copy
1#include <stdint.h>
2#include <avr/interrupt.h>
3#include <avr/io.h>
4#include <avr/pgmspace.h>
8/*
9* The audio data needs to be unsigned, 8-bit, 8000 Hz, and small enough
11*
15*
17* https://thieumsweb.free.fr/english/gbacss.html
18* Then add "PROGMEM" in the right place. I hacked it up to dump the
samples
20*
21* https://musicthing.blogspot.com/2005/05/tiny-music-makers-pt-4-mac-
startup.html
26*
27* (starfox) nb. under sox 12.18 (distributed in CentOS 5), i needed to run
28* the following command to convert my wav file to the appropriate format:
30*/
31
32#include "sounddata.h"
33
35int speakerPin = 11; // Can be either 3 or 11, two PWM outputs connected
to Timer 2
37byte lastSample;
38
39
40void stopPlayback()
41{
44
47
50
51 digitalWrite(speakerPin, LOW);
52}
53
55ISR(TIMER1_COMPA_vect) {
58 stopPlayback();
59 }
60 else {
61 if(speakerPin==11){
64 } else {
66 }
67 }
68 }
69 else {
70 if(speakerPin==11){
71 OCR2A = pgm_read_byte(&sounddata_data[sample]);
72 } else {
73 OCR2B = pgm_read_byte(&sounddata_data[sample]);
74 }
75 }
76
77 ++sample;
78}
79
80void startPlayback()
81{
82 pinMode(speakerPin, OUTPUT);
83
85 // pin.
86
89
93
94 if(speakerPin==11){
99 // No prescaler (p.158)
101
104 } else {
111
114 }
115
116
117
118
119
121
122 cli();
123
128
131
132 // Set the compare register (OCR1A).
136
139
141 sample = 0;
142 sei();
143}
144
145
146void setup()
147{
150 startPlayback();
151}
152
153void loop()
154{
156}
The above sketch also requires the
sounddata.h
file which you can find below:
Copy
8128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
9128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128,
10128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
11128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
12128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
13128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
14128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
15128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
16128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128,
17128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
129, 127, 129, 128, 127, 133,
18117, 109, 125, 121, 116, 132, 140, 126, 114, 114, 116, 120, 114, 93, 73,
66, 76, 116, 142, 129,
19128, 129, 120, 119, 118, 104, 87, 123, 181, 194, 196, 198, 189, 176, 160,
162, 172, 164, 164, 183,
20197, 188, 168, 167, 170, 165, 185, 209, 206, 196, 196, 199, 185, 162,
156, 167, 176, 173, 170, 166,
21151, 142, 140, 134, 130, 127, 113, 86, 67, 66, 69, 75, 73, 75, 86, 90, 91,
84, 65, 48,
2241, 30, 26, 56, 91, 88, 72, 70, 73, 82, 89, 73, 57, 60, 74, 89, 92, 77, 63,
60,
2353, 47, 56, 64, 63, 61, 56, 54, 52, 36, 16, 22, 51, 66, 67, 70, 76, 88, 99,
92,
2477, 74, 85, 100, 106, 97, 83, 85, 96, 108, 133, 160, 164, 144, 113, 96, 91,
82, 74, 76,
2589, 97, 97, 97, 82, 54, 40, 41, 41, 43, 56, 74, 78, 64, 55, 64, 72, 72, 84,
102,
26108, 116, 126, 127, 124, 127, 134, 134, 138, 148, 152, 156, 164, 165,
169, 171, 160, 156, 157, 152,
27151, 145, 133, 136, 153, 166, 165, 163, 165, 161, 156, 158, 155, 147,
148, 160, 185, 209, 215, 220,
28220, 204, 200, 208, 205, 200, 202, 209, 214, 213, 205, 198, 194, 194,
203, 219, 231, 235, 230, 219,
29200, 184, 177, 170, 170, 177, 172, 164, 163, 158, 156, 160, 163, 161,
142, 116, 103, 96, 89, 93,
30101, 105, 111, 116, 120, 110, 89, 80, 78, 75, 73, 80, 93, 91, 77, 69, 70,
77, 91, 98,
3189, 87, 93, 95, 95, 94, 97, 96, 91, 94, 99, 100, 101, 95, 83, 78, 79, 71, 56,
41,
3237, 53, 64, 63, 72, 82, 83, 82, 80, 73, 67, 69, 69, 66, 68, 79, 99, 121, 143,
165,
33180, 174, 148, 131, 122, 112, 115, 120, 121, 126, 122, 108, 87, 72, 71,
73, 79, 81, 83, 86,
3483, 77, 70, 71, 85, 100, 112, 118, 130, 146, 154, 166, 174, 172, 172, 161,
147, 146, 153, 157,
35161, 165, 168, 170, 162, 138, 122, 121, 121, 123, 128, 138, 151, 161,
165, 161, 153, 150, 149, 147,
36136, 129, 140, 150, 156, 176, 194, 193, 179, 168, 167, 174, 185, 188,
181, 174, 164, 156, 156, 155,
37163, 185, 210, 224, 229, 235, 233, 215, 195, 176, 168, 170, 171, 168,
162, 162, 163, 165, 174, 181,
38184, 172, 151, 135, 125, 125, 132, 138, 139, 139, 139, 133, 121, 116,
117, 115, 104, 94, 94, 94,
3992, 90, 82, 70, 64, 69, 77, 82, 87, 85, 85, 92, 97, 105, 112, 108, 103, 107,
116, 122,
40121, 115, 101, 87, 80, 71, 67, 72, 70, 68, 78, 82, 78, 78, 79, 81, 79, 68,
59, 57,
4153, 60, 83, 106, 125, 146, 174, 192, 188, 186, 180, 161, 155, 157, 158,
156, 152, 148, 131, 117,
42111, 100, 97, 101, 104, 107, 110, 113, 112, 108, 106, 108, 122, 130, 141,
164, 175, 180, 185, 186,
43186, 182, 174, 167, 155, 150, 154, 155, 143, 132, 136, 139, 127, 114,
108, 107, 104, 103, 114, 120,
44124, 131, 134, 132, 123, 115, 109, 101, 108, 130, 144, 154, 161, 171,
184, 184, 171, 155, 147, 155,
45165, 165, 151, 142, 144, 136, 137, 152, 158, 162, 177, 200, 209, 206,
201, 181, 163, 159, 154, 154,
46151, 146, 161, 176, 170, 168, 175, 181, 176, 160, 148, 141, 138, 140,
140, 139, 140, 148, 155, 152,
47146, 135, 123, 111, 103, 110, 113, 100, 81, 62, 55, 52, 40, 33, 38, 60, 86,
95, 99, 106,
48111, 113, 105, 91, 87, 94, 101, 106, 103, 90, 76, 67, 63, 68, 72, 68, 63,
58, 68, 86,
4982, 68, 60, 56, 53, 45, 37, 40, 58, 77, 92, 110, 128, 149, 169, 174, 161,
151, 144, 139,
50142, 146, 146, 147, 142, 132, 129, 127, 116, 99, 94, 103, 113, 119, 122,
128, 133, 128, 119, 118,
51132, 160, 193, 215, 221, 222, 226, 224, 217, 211, 200, 181, 166, 158,
152, 148, 139, 125, 118, 118,
52119, 122, 123, 123, 124, 126, 127, 124, 127, 141, 143, 131, 118, 107,
110, 127, 146, 159, 163, 165,
53166, 164, 164, 160, 146, 131, 124, 135, 147, 145, 140, 138, 130, 124,
130, 136, 145, 163, 177, 182,
54181, 179, 177, 169, 159, 154, 155, 165, 176, 184, 195, 195, 183, 173,
163, 156, 158, 160, 159, 165,
55171, 164, 154, 154, 159, 167, 170, 167, 157, 141, 128, 120, 115, 111,
102, 95, 87, 64, 50, 49,
5645, 54, 77, 101, 123, 136, 139, 136, 128, 119, 112, 105, 101, 110, 123,
112, 94, 88, 78, 72,
5783, 89, 80, 69, 65, 57, 58, 64, 59, 53, 39, 16, 18, 36, 46, 66, 92, 107, 119,
135,
58145, 150, 160, 158, 147, 145, 144, 150, 160, 153, 150, 150, 140, 128,
120, 116, 104, 91, 88, 90,
59106, 123, 123, 123, 114, 100, 105, 119, 142, 181, 211, 222, 220, 214,
208, 204, 201, 186, 171, 166,
60162, 154, 138, 128, 120, 101, 93, 94, 103, 119, 117, 109, 109, 112, 119,
121, 121, 124, 122, 119,
61117, 124, 142, 158, 174, 183, 173, 168, 165, 149, 135, 132, 126, 119,
124, 127, 125, 133, 126, 111,
62116, 123, 127, 135, 145, 157, 167, 174, 176, 177, 182, 181, 184, 194,
194, 198, 213, 219, 219, 219,
63206, 184, 164, 153, 154, 163, 166, 162, 165, 164, 154, 154, 160, 161,
165, 166, 158, 146, 140, 130,
64122, 121, 109, 95, 89, 74, 61, 65, 74, 88, 110, 132, 149, 159, 149, 124,
107, 99, 91, 92,
6598, 101, 101, 90, 81, 84, 86, 82, 82, 80, 68, 58, 56, 53, 47, 42, 37, 35, 35,
30,
6628, 31, 40, 56, 74, 91, 99, 98, 101, 110, 114, 111, 110, 119, 127, 133,
140, 139, 128, 118,
67116, 109, 94, 87, 83, 79, 89, 110, 119, 116, 117, 117, 114, 117, 116, 119,
137, 164, 191, 204,
68192, 180, 180, 175, 161, 152, 149, 139, 128, 122, 111, 98, 89, 88, 93, 97,
94, 98, 104, 101,
69107, 119, 117, 121, 140, 152, 157, 164, 165, 171, 183, 190, 194, 191,
182, 172, 166, 154, 137, 132,
70134, 134, 138, 141, 130, 120, 123, 123, 120, 117, 109, 110, 125, 150,
168, 164, 163, 179, 196, 210,
71218, 220, 224, 227, 230, 238, 237, 218, 205, 202, 194, 189, 188, 184,
181, 181, 182, 174, 162, 161,
72168, 181, 194, 187, 176, 170, 156, 151, 143, 127, 125, 125, 116, 103, 94,
95, 107, 124, 145, 161,
73159, 151, 153, 145, 123, 106, 95, 85, 82, 86, 87, 78, 74, 79, 79, 73, 64,
58, 62, 62,
7464, 59, 43, 41, 53, 59, 57, 51, 47, 49, 71, 99, 107, 105, 98, 87, 93, 109,
117, 114,
75110, 113, 120, 132, 136, 131, 129, 123, 112, 105, 97, 95, 103, 115, 123,
125, 130, 140, 145, 145,
76137, 134, 142, 147, 157, 176, 187, 183, 171, 157, 142, 132, 132, 133,
131, 127, 111, 92, 84, 83,
7781, 72, 63, 60, 69, 90, 112, 122, 115, 112, 124, 131, 135, 144, 145, 149,
161, 174, 184, 181,
78171, 160, 148, 143, 138, 127, 119, 119, 126, 130, 120, 107, 100, 99, 104,
109, 105, 95, 95, 106,
79121, 138, 149, 158, 165, 170, 183, 200, 214, 227, 233, 236, 236, 225,
214, 206, 194, 188, 181, 173,
80174, 175, 176, 174, 164, 159, 159, 153, 149, 150, 154, 166, 172, 160,
146, 136, 130, 131, 127, 112,
8196, 91, 97, 107, 117, 125, 125, 120, 119, 120, 119, 112, 96, 80, 70, 65,
67, 69, 63, 63,
8261, 48, 41, 46, 58, 73, 84, 91, 90, 85, 88, 88, 84, 79, 74, 84, 94, 99, 116,
128,
83122, 111, 104, 99, 96, 101, 117, 128, 127, 124, 130, 139, 139, 138, 133,
115, 105, 115, 131, 141,
84147, 149, 147, 149, 159, 162, 159, 158, 155, 156, 160, 162, 168, 168,
163, 166, 168, 148, 121, 118,
85128, 127, 127, 124, 108, 93, 85, 76, 67, 56, 58, 82, 102, 108, 122, 137,
135, 131, 134, 133,
86135, 145, 158, 165, 166, 167, 161, 152, 151, 147, 140, 128, 117, 116,
116, 113, 117, 115, 108, 105,
87105, 99, 91, 98, 112, 115, 120, 133, 145, 158, 171, 182, 188, 190, 201,
222, 235, 239, 241, 245,
88239, 230, 224, 214, 196, 178, 176, 183, 191, 200, 199, 189, 175, 159,
148, 140, 135, 150, 173, 185,
89185, 178, 157, 135, 125, 115, 104, 101, 102, 100, 95, 93, 91, 81, 73, 74,
80, 87, 77, 72,
9072, 56, 45, 47, 45, 42, 39, 37, 27, 16, 24, 54, 82, 92, 91, 94, 92, 88, 84,
75,
9173, 80, 93, 113, 127, 129, 117, 107, 100, 90, 85, 82, 83, 101, 122, 134,
139, 141, 137, 130,
92126, 116, 108, 120, 145, 168, 176, 173, 165, 151, 142, 144, 146, 149,
150, 155, 163, 158, 152, 144,
93136, 140, 142, 136, 132, 126, 123, 122, 118, 120, 120, 115, 115, 108, 91,
82, 85, 98, 120, 144,
94163, 171, 156, 138, 134, 129, 123, 128, 140, 155, 166, 169, 157, 140,
132, 125, 121, 121, 115, 110,
95115, 113, 101, 92, 87, 83, 83, 86, 85, 81, 88, 106, 120, 127, 126, 121,
126, 144, 161, 167,
96166, 173, 196, 217, 224, 226, 220, 211, 213, 217, 208, 200, 197, 187,
184, 190, 194, 198, 199, 186,
97174, 167, 160, 160, 173, 188, 198, 206, 200, 181, 169, 152, 130, 119,
110, 110, 125, 126, 115, 102,
9883, 68, 66, 72, 75, 79, 75, 61, 51, 49, 43, 38, 40, 41, 35, 32, 39, 48, 59,
72,
9987, 98, 91, 87, 92, 84, 71, 66, 73, 91, 110, 123, 127, 113, 95, 88, 82, 76,
76, 84,
10096, 109, 119, 123, 129, 127, 119, 121, 122, 126, 139, 148, 162, 173,
169, 158, 142, 127, 121, 121,
101124, 125, 134, 149, 154, 158, 145, 119, 114, 119, 119, 128, 140, 142,
138, 130, 123, 125, 128, 125,
102128, 137, 141, 147, 157, 156, 149, 158, 174, 171, 153, 139, 127, 123,
130, 136, 151, 166, 166, 158,
103144, 130, 122, 113, 110, 115, 119, 122, 122, 112, 96, 85, 82, 79, 82, 95,
108, 112, 107, 103,
104111, 126, 125, 113, 118, 129, 136, 149, 162, 173, 184, 194, 198, 186,
179, 191, 197, 190, 190, 198,
105201, 193, 187, 185, 188, 197, 202, 206, 212, 213, 207, 198, 191, 193,
203, 203, 191, 178, 160, 137,
106123, 116, 112, 120, 129, 122, 103, 88, 80, 63, 47, 46, 56, 65, 54, 41, 42,
45, 46, 47,
10754, 64, 60, 61, 77, 79, 73, 90, 111, 109, 98, 100, 102, 93, 88, 95, 116,
137, 141, 140,
108137, 122, 104, 97, 99, 101, 106, 110, 115, 127, 130, 129, 139, 148, 146,
143, 147, 144, 139, 149,
109168, 172, 155, 139, 129, 117, 107, 110, 121, 133, 144, 153, 154, 138,
118, 103, 94, 96, 112, 136,
110150, 143, 129, 125, 129, 133, 145, 158, 156, 149, 151, 156, 160, 162,
160, 153, 143, 131, 117, 107,
111107, 110, 113, 123, 134, 131, 118, 111, 112, 104, 90, 99, 118, 121, 123,
131, 121, 104, 101, 112,
112127, 132, 127, 126, 128, 125, 118, 125, 133, 123, 111, 107, 113, 124,
133, 150, 170, 179, 181, 183,
113184, 180, 176, 182, 188, 193, 198, 205, 213, 211, 209, 215, 222, 226,
225, 228, 232, 224, 204, 190,
114192, 199, 196, 193, 186, 168, 151, 136, 126, 125, 126, 123, 112, 95, 77,
64, 53, 40, 32, 34,
11543, 47, 44, 40, 42, 48, 50, 48, 51, 50, 47, 52, 57, 63, 75, 81, 88, 95, 96,
98,
11697, 88, 89, 111, 137, 148, 149, 144, 125, 109, 101, 101, 109, 120, 123,
124, 135, 142, 143, 153,
117160, 156, 152, 148, 141, 135, 131, 128, 129, 126, 113, 105, 108, 101,
88, 91, 99, 104, 114, 118,
118116, 114, 98, 78, 78, 91, 101, 119, 134, 135, 134, 135, 142, 157, 162,
155, 150, 147, 140, 140,
119151, 154, 145, 133, 119, 115, 116, 102, 91, 99, 106, 106, 109, 104, 92,
89, 87, 82, 85, 91,
120102, 123, 134, 131, 129, 121, 116, 126, 133, 132, 127, 121, 113, 114,
121, 124, 123, 118, 110, 113,
121119, 114, 117, 137, 153, 158, 160, 159, 158, 158, 156, 152, 154, 163,
176, 193, 210, 213, 206, 205,
122209, 214, 223, 226, 220, 217, 209, 199, 198, 192, 182, 178, 178, 174,
161, 151, 153, 150, 145, 136,
123119, 104, 86, 68, 60, 49, 44, 52, 61, 68, 69, 58, 52, 56, 57, 57, 60, 56,
49, 51,
12459, 69, 74, 80, 95, 115, 130, 134, 133, 134, 134, 145, 168, 173, 168,
168, 162, 149, 145, 147,
125154, 168, 178, 183, 184, 174, 166, 168, 175, 174, 160, 154, 152, 138,
131, 133, 126, 111, 100, 94,
12697, 93, 86, 97, 105, 101, 102, 107, 108, 102, 92, 87, 89, 97, 117, 149,
170, 162, 148, 150,
127159, 168, 176, 176, 165, 147, 133, 131, 137, 138, 130, 122, 119, 117,
114, 110, 104, 104, 107, 101,
12896, 91, 82, 81, 83, 79, 82, 100, 122, 141, 147, 140, 132, 121, 113, 119,
125, 122, 111, 103,
129108, 113, 117, 124, 120, 116, 119, 117, 128, 142, 141, 148, 159, 161,
163, 169, 171, 171, 176, 183,
130186, 181, 187, 202, 205, 198, 192, 192, 193, 195, 203, 204, 191, 184,
182, 179, 189, 195, 185, 180,
131176, 165, 159, 161, 162, 155, 142, 130, 121, 104, 78, 66, 65, 46, 34, 51,
65, 66, 62, 48,
13235, 34, 36, 35, 42, 49, 49, 53, 57, 57, 66, 76, 84, 95, 109, 120, 130, 137,
129, 122,
133133, 143, 148, 152, 152, 157, 165, 164, 168, 183, 186, 181, 188, 189,
176, 171, 173, 173, 165, 149,
134140, 139, 139, 134, 127, 118, 95, 78, 82, 82, 75, 76, 69, 64, 78, 90, 85,
80, 79, 83,
13598, 117, 131, 145, 153, 153, 153, 151, 151, 155, 157, 152, 146, 146,
141, 133, 136, 134, 125, 123,
136121, 123, 136, 137, 117, 102, 94, 84, 90, 98, 87, 82, 93, 104, 108, 115,
130, 138, 135, 128,
137125, 122, 114, 113, 112, 101, 99, 107, 109, 110, 114, 117, 113, 103,
102, 118, 141, 151, 146, 144,
138151, 165, 181, 181, 176, 181, 179, 177, 185, 190, 188, 185, 182, 174,
172, 175, 172, 177, 185, 187,
139187, 183, 181, 192, 203, 202, 185, 175, 188, 200, 200, 190, 175, 162,
152, 146, 141, 128, 112, 104,
14094, 76, 69, 77, 78, 73, 63, 51, 36, 24, 28, 39, 47, 54, 55, 54, 59, 67, 74,
74,
14173, 86, 103, 113, 121, 126, 125, 127, 136, 142, 145, 155, 169, 183, 185,
178, 170, 166, 172, 183,
142190, 187, 172, 166, 172, 167, 161, 158, 145, 134, 126, 115, 108, 94, 74,
66, 67, 63, 58, 61,
14362, 65, 74, 73, 66, 69, 85, 103, 117, 131, 137, 139, 148, 152, 146, 138,
138, 144, 140, 133,
144140, 150, 140, 128, 129, 124, 116, 118, 121, 124, 128, 128, 116, 96, 86,
91, 105, 116, 115, 117,
145127, 128, 130, 140, 147, 145, 138, 123, 118, 126, 125, 112, 102, 101,
106, 112, 110, 112, 113, 102,
14692, 93, 102, 117, 141, 164, 165, 155, 161, 173, 176, 178, 181, 192, 198,
188, 181, 185, 183, 172,
147165, 159, 158, 164, 163, 158, 164, 171, 169, 164, 164, 176, 190, 194,
185, 173, 169, 179, 189, 186,
148179, 169, 157, 141, 127, 126, 124, 109, 93, 80, 74, 78, 77, 65, 46, 33,
32, 34, 33, 38,
14951, 62, 58, 52, 59, 68, 69, 68, 79, 96, 109, 117, 120, 127, 134, 139, 148,
148, 152, 175,
150191, 190, 190, 191, 183, 166, 160, 171, 189, 199, 189, 169, 157, 161,
171, 173, 166, 155, 144, 129,
151112, 107, 107, 96, 86, 88, 86, 83, 82, 83, 89, 88, 89, 96, 95, 106, 133,
152, 149, 130,
152123, 127, 122, 123, 131, 132, 132, 130, 124, 120, 120, 121, 123, 123,
123, 128, 132, 131, 132, 130,
153118, 103, 97, 113, 142, 163, 164, 149, 132, 127, 133, 142, 146, 146,
137, 116, 102, 103, 103, 97,
15495, 96, 100, 108, 106, 98, 97, 94, 87, 80, 82, 102, 138, 167, 171, 159,
151, 154, 168, 183,
155189, 188, 188, 182, 172, 168, 169, 166, 154, 148, 153, 156, 155, 154,
159, 170, 169, 156, 151, 167,
156193, 208, 199, 177, 169, 177, 188, 193, 191, 183, 170, 155, 139, 120,
110, 105, 96, 89, 83, 75,
15771, 60, 42, 32, 28, 22, 21, 30, 51, 71, 70, 53, 42, 42, 51, 63, 75, 95, 116,
127,
158128, 125, 132, 145, 153, 163, 171, 176, 184, 193, 196, 190, 183, 174,
159, 157, 173, 185, 183, 170,
159160, 165, 177, 184, 176, 157, 139, 125, 107, 96, 97, 97, 98, 100, 95, 93,
97, 99, 103, 100,
16089, 89, 98, 113, 137, 148, 145, 129, 106, 97, 96, 97, 102, 108, 118, 124,
119, 112, 110, 110,
161116, 126, 125, 125, 139, 151, 153, 150, 137, 126, 128, 138, 156, 168,
169, 159, 150, 145, 141, 141,
162145, 140, 125, 109, 95, 88, 86, 86, 92, 96, 97, 99, 99, 97, 92, 80, 67, 73,
96, 117,
163139, 157, 162, 164, 160, 158, 164, 167, 169, 172, 171, 167, 160, 154,
148, 144, 142, 142, 146, 151,
164153, 160, 172, 172, 168, 172, 173, 179, 192, 192, 188, 186, 178, 182,
193, 194, 194, 185, 169, 152,
165133, 115, 98, 86, 84, 80, 73, 67, 56, 43, 37, 31, 24, 27, 32, 34, 51, 68,
65, 56,
16654, 57, 63, 74, 91, 106, 123, 141, 154, 164, 170, 170, 173, 186, 193,
193, 199, 200, 196, 187,
167172, 163, 158, 155, 167, 174, 168, 166, 166, 165, 174, 180, 167, 151,
143, 131, 115, 111, 110, 106,
168106, 116, 126, 129, 122, 111, 104, 95, 85, 95, 113, 117, 122, 125, 116,
102, 86, 76, 79, 85,
16986, 88, 93, 93, 95, 101, 98, 99, 109, 115, 120, 130, 136, 138, 140, 144,
147, 148, 146, 144,
170153, 160, 159, 155, 146, 138, 137, 135, 127, 118, 112, 105, 97, 93, 87,
79, 83, 97, 100, 90,
17187, 91, 83, 63, 62, 78, 90, 113, 150, 172, 169, 159, 153, 154, 160, 165,
166, 162, 158, 156,
172156, 157, 154, 155, 161, 162, 162, 169, 169, 168, 175, 178, 180, 194,
205, 202, 197, 199, 198, 188,
173178, 182, 202, 210, 190, 168, 158, 141, 123, 118, 110, 91, 77, 76, 70,
56, 51, 50, 40, 30,
17428, 32, 33, 34, 50, 64, 62, 69, 80, 75, 78, 94, 105, 121, 147, 175, 196,
198, 197, 206,
175214, 217, 218, 216, 210, 199, 191, 175, 160, 165, 172, 165, 164, 171,
172, 165, 158, 157, 161, 158,
176152, 151, 142, 124, 117, 118, 115, 122, 141, 154, 148, 131, 120, 112,
105, 102, 108, 112, 104, 100,
177105, 104, 98, 89, 76, 61, 53, 58, 62, 56, 56, 66, 72, 81, 98, 105, 101,
107, 125, 134,
178135, 135, 134, 136, 139, 142, 141, 138, 140, 143, 139, 128, 118, 114,
108, 101, 101, 106, 103, 89,
17975, 66, 61, 67, 83, 95, 94, 87, 76, 61, 49, 51, 62, 72, 89, 115, 139, 149,
146, 141,
180139, 139, 141, 139, 131, 129, 132, 138, 143, 148, 156, 163, 164, 166,
174, 178, 172, 170, 178, 194,
181217, 227, 220, 217, 225, 229, 225, 219, 213, 209, 204, 200, 194, 181,
169, 153, 132, 121, 110, 100,
18298, 100, 103, 94, 74, 59, 53, 49, 47, 47, 51, 57, 73, 93, 98, 94, 91, 95,
105, 118,
183141, 166, 183, 189, 192, 200, 200, 204, 214, 209, 204, 197, 181, 174,
165, 156, 160, 158, 151, 153,
184156, 155, 158, 157, 156, 164, 165, 163, 163, 151, 139, 140, 141, 145,
151, 155, 158, 160, 162, 151,
185127, 111, 112, 114, 110, 100, 90, 90, 98, 100, 94, 84, 70, 59, 50, 45, 47,
51, 59, 76,
18690, 104, 112, 111, 114, 131, 155, 165, 155, 145, 141, 141, 146, 140,
125, 124, 129, 126, 116, 110,
187106, 98, 90, 85, 82, 82, 78, 64, 47, 43, 51, 59, 65, 77, 90, 89, 73, 58, 57,
70,
18887, 94, 92, 106, 127, 138, 142, 137, 133, 135, 131, 123, 117, 115, 120,
126, 130, 139, 146, 147,
189148, 152, 156, 164, 168, 166, 181, 209, 230, 231, 222, 225, 236, 237,
231, 220, 210, 204, 196, 188,
190174, 156, 143, 130, 114, 101, 91, 80, 69, 68, 74, 77, 73, 59, 47, 46, 49,
55, 57, 56,
19163, 88, 113, 119, 120, 128, 131, 137, 153, 166, 179, 189, 193, 199, 200,
198, 200, 198, 191, 183,
192174, 165, 156, 156, 158, 151, 143, 147, 153, 155, 155, 150, 147, 162,
180, 186, 177, 159, 152, 155,
193153, 152, 154, 149, 146, 160, 159, 135, 120, 112, 110, 113, 107, 97, 85,
77, 84, 94, 88, 70,
19461, 59, 52, 51, 53, 48, 56, 94, 130, 138, 134, 129, 134, 150, 162, 168,
164, 151, 145, 144,
195137, 132, 128, 126, 129, 127, 129, 130, 115, 102, 95, 80, 74, 82, 82, 72,
61, 59, 61, 62,
19674, 99, 113, 106, 92, 85, 84, 86, 91, 96, 99, 110, 129, 138, 140, 140,
138, 137, 133, 124,
197120, 121, 126, 134, 140, 137, 136, 147, 161, 171, 176, 174, 170, 189,
221, 237, 238, 236, 232, 231,
198231, 232, 228, 216, 201, 190, 179, 164, 155, 150, 131, 111, 101, 90, 82,
72, 64, 68, 74, 75,
19976, 71, 61, 54, 49, 50, 54, 58, 78, 116, 136, 137, 132, 130, 134, 140,
153, 170, 175, 185,
200197, 202, 209, 210, 197, 185, 184, 181, 171, 161, 154, 151, 147, 143,
141, 144, 151, 156, 160, 173,
201190, 200, 205, 197, 180, 174, 169, 164, 165, 160, 152, 154, 155, 154,
149, 137, 122, 106, 94, 90,
20286, 80, 67, 56, 64, 72, 66, 57, 48, 40, 35, 34, 46, 70, 87, 99, 118, 129,
126, 129,
203135, 143, 149, 147, 147, 141, 129, 127, 132, 131, 121, 111, 120, 133,
132, 129, 121, 105, 90, 80,
20481, 91, 93, 85, 82, 88, 98, 109, 117, 122, 118, 112, 114, 111, 99, 101,
102, 87, 78, 90,
205113, 133, 140, 136, 128, 117, 109, 109, 109, 108, 113, 123, 131, 132,
135, 141, 148, 160, 171, 178,
206186, 196, 207, 213, 219, 225, 217, 207, 209, 214, 207, 188, 181, 180,
167, 155, 151, 138, 110, 87,
20780, 77, 68, 64, 65, 68, 71, 71, 69, 67, 62, 59, 64, 68, 61, 58, 78, 107,
130, 145,
208145, 139, 141, 145, 151, 164, 181, 196, 205, 212, 214, 205, 191, 181,
181, 187, 191, 183, 166, 156,
209155, 154, 143, 141, 157, 175, 188, 199, 205, 206, 202, 191, 181, 170,
162, 164, 167, 155, 140, 143,
210147, 142, 136, 122, 100, 83, 77, 83, 89, 79, 58, 47, 52, 61, 63, 53, 45,
47, 51, 59,
21171, 75, 75, 84, 97, 105, 107, 107, 112, 121, 129, 134, 138, 137, 124,
116, 118, 116, 105, 99,
212112, 134, 149, 145, 129, 116, 103, 99, 109, 118, 118, 115, 121, 129,
129, 128, 123, 114, 113, 114,
213115, 120, 117, 107, 106, 107, 104, 104, 115, 125, 127, 125, 121, 123,
125, 119, 116, 113, 110, 124,
214147, 152, 151, 165, 173, 173, 188, 202, 203, 203, 210, 217, 221, 220,
208, 199, 204, 208, 202, 196,
215186, 176, 164, 147, 129, 111, 93, 81, 74, 70, 63, 56, 55, 57, 70, 78, 74,
67, 61, 55,
21655, 58, 59, 55, 59, 85, 115, 130, 139, 148, 149, 153, 170, 182, 183, 185,
188, 189, 188, 190,
217195, 188, 181, 185, 188, 180, 168, 160, 163, 168, 161, 161, 179, 190,
194, 199, 200, 198, 195, 192,
218177, 158, 155, 158, 157, 151, 140, 134, 132, 122, 105, 94, 85, 80, 87,
94, 91, 81, 63, 49,
21955, 69, 78, 77, 72, 75, 90, 101, 100, 87, 74, 73, 87, 106, 111, 107, 110,
114, 117, 126,
220132, 122, 105, 92, 92, 99, 99, 95, 106, 122, 125, 128, 126, 112, 113,
135, 144, 134, 123, 119,
221119, 119, 117, 110, 106, 106, 103, 104, 114, 122, 127, 122, 112, 109,
106, 108, 117, 116, 113, 124,
222132, 131, 134, 136, 126, 114, 108, 122, 152, 170, 167, 164, 173, 184,
184, 182, 182, 189, 202, 210,
223212, 209, 202, 203, 208, 205, 200, 196, 188, 175, 163, 158, 151, 131,
104, 82, 74, 72, 70, 68,
22467, 71, 80, 83, 79, 70, 64, 58, 52, 51, 54, 60, 74, 89, 104, 127, 151, 156,
150, 161,
225179, 178, 164, 159, 168, 181, 189, 190, 190, 187, 181, 182, 187, 191,
195, 198, 193, 177, 166, 177,
226195, 196, 186, 184, 189, 187, 182, 185, 189, 178, 158, 143, 140, 139,
130, 119, 112, 106, 96, 86,
22785, 91, 96, 95, 87, 74, 64, 69, 81, 82, 78, 82, 91, 92, 92, 97, 97, 88, 73,
66,
22878, 99, 112, 118, 118, 109, 104, 111, 116, 113, 110, 107, 103, 99, 93,
96, 104, 106, 113, 125,
229128, 128, 135, 143, 145, 135, 120, 111, 108, 106, 104, 100, 96, 94, 97,
104, 109, 115, 117, 114,
230114, 107, 98, 105, 116, 115, 114, 122, 122, 114, 113, 121, 126, 118,
112, 121, 136, 146, 151, 159,
231172, 175, 166, 165, 175, 185, 190, 196, 203, 198, 192, 195, 195, 190,
186, 185, 181, 171, 160, 156,
232155, 141, 109, 86, 77, 74, 78, 83, 83, 83, 82, 83, 82, 77, 70, 66, 61, 54,
53, 67,
23384, 93, 103, 120, 133, 143, 154, 164, 173, 173, 156, 150, 162, 174, 178,
180, 180, 179, 179, 185,
234195, 199, 197, 196, 189, 184, 190, 204, 203, 186, 177, 183, 187, 186,
187, 191, 194, 187, 167, 147,
235136, 133, 130, 125, 121, 116, 108, 101, 95, 90, 89, 87, 85, 86, 90, 100,
100, 83, 79, 93,
236100, 93, 85, 80, 81, 83, 80, 80, 90, 98, 100, 106, 108, 108, 108, 107,
106, 109, 113, 108,
237100, 95, 92, 98, 103, 102, 115, 138, 146, 146, 145, 143, 150, 150, 131,
108, 94, 91, 95, 101,
238103, 104, 104, 94, 88, 93, 96, 99, 104, 104, 105, 115, 119, 108, 107,
117, 122, 116, 111, 125,
239147, 152, 143, 130, 129, 140, 152, 165, 173, 173, 172, 173, 176, 180,
189, 193, 189, 181, 179, 190,
240199, 190, 181, 177, 165, 149, 138, 132, 133, 128, 107, 88, 81, 84, 86,
83, 79, 77, 78, 76,
24168, 62, 56, 47, 40, 39, 53, 81, 98, 95, 104, 125, 143, 156, 163, 170, 176,
171, 162, 156,
242150, 156, 167, 169, 172, 179, 186, 192, 192, 182, 173, 175, 179, 176,
179, 188, 187, 182, 183, 189,
243197, 196, 185, 181, 182, 181, 175, 161, 147, 141, 133, 122, 122, 125,
114, 106, 100, 85, 77, 84,
24492, 89, 81, 82, 88, 89, 87, 91, 93, 77, 65, 66, 65, 70, 83, 84, 85, 95, 99,
102,
245111, 112, 108, 102, 96, 95, 94, 93, 89, 83, 79, 89, 104, 120, 139, 152,
154, 150, 149, 150,
246150, 151, 132, 104, 94, 91, 93, 107, 116, 107, 91, 83, 88, 94, 96, 95, 95,
95, 99, 113,
247128, 129, 131, 140, 139, 133, 138, 153, 163, 162, 156, 153, 158, 165,
170, 171, 174, 183, 186, 184,
248188, 190, 188, 185, 177, 174, 179, 187, 199, 201, 191, 180, 170, 157,
142, 135, 135, 127, 114, 112,
249117, 114, 100, 84, 82, 84, 77, 70, 64, 55, 47, 43, 38, 40, 53, 74, 94, 103,
115, 143,
250161, 162, 165, 165, 167, 178, 176, 161, 158, 168, 175, 181, 188, 192,
193, 186, 174, 173, 180, 181,
251176, 173, 171, 179, 194, 198, 196, 201, 203, 198, 190, 189, 197, 195,
180, 168, 158, 148, 139, 127,
252119, 121, 119, 113, 105, 88, 84, 98, 97, 80, 71, 80, 96, 102, 93, 82, 79,
76, 65, 61,
25371, 82, 85, 88, 94, 101, 105, 104, 100, 100, 96, 87, 81, 73, 71, 78, 76,
63, 59, 75,
254104, 124, 124, 127, 140, 147, 143, 134, 127, 128, 124, 107, 91, 87, 92,
101, 105, 98, 85, 82,
25581, 74, 76, 83, 85, 86, 86, 91, 109, 127, 131, 129, 134, 138, 140, 151,
161, 167, 175, 170,
256163, 169, 175, 178, 183, 183, 178, 181, 189, 187, 185, 189, 187, 178,
171, 178, 194, 198, 188, 172,
257156, 145, 141, 138, 129, 122, 123, 121, 120, 116, 106, 103, 99, 89, 81,
71, 57, 50, 51, 48,
25846, 51, 61, 80, 100, 110, 113, 124, 137, 148, 161, 166, 166, 171, 169,
157, 155, 160, 166, 175,
259184, 186, 180, 174, 168, 162, 159, 159, 157, 155, 159, 171, 184, 190,
195, 201, 201, 196, 191, 187,
260188, 185, 173, 161, 152, 146, 140, 132, 125, 127, 124, 109, 93, 80, 77,
86, 90, 85, 82, 87,
26188, 78, 67, 64, 69, 72, 72, 80, 91, 98, 102, 103, 103, 105, 112, 117, 115,
110, 98, 88,
26280, 67, 70, 84, 85, 75, 74, 83, 102, 119, 121, 126, 141, 142, 132, 124,
120, 123, 121, 109,
263103, 105, 108, 113, 114, 106, 96, 88, 82, 76, 76, 84, 90, 94, 103, 114,
126, 137, 135, 126,
264128, 142, 154, 161, 168, 175, 173, 162, 159, 164, 169, 178, 187, 189,
192, 188, 178, 170, 164, 164,
265171, 181, 183, 179, 178, 176, 163, 148, 140, 139, 134, 126, 118, 109,
108, 112, 115, 115, 110, 102,
26695, 86, 79, 75, 69, 66, 62, 58, 62, 65, 72, 83, 89, 96, 106, 116, 129, 141,
151, 156,
267161, 168, 173, 172, 164, 162, 169, 180, 190, 194, 193, 187, 175, 167,
156, 147, 160, 174, 181, 193,
268200, 202, 204, 203, 201, 196, 187, 182, 179, 177, 175, 169, 160, 150,
138, 135, 135, 135, 131, 116,
269102, 92, 85, 90, 103, 106, 99, 93, 90, 86, 84, 78, 78, 85, 89, 96, 102,
106, 107, 104,
270105, 115, 120, 123, 130, 127, 109, 95, 93, 90, 86, 84, 89, 88, 82, 90,
101, 108, 118, 124,
271124, 121, 118, 119, 118, 122, 128, 122, 110, 106, 108, 107, 103, 99, 93,
87, 84, 85, 83, 78,
27280, 85, 93, 107, 114, 121, 134, 138, 138, 141, 149, 159, 164, 170, 175,
172, 176, 189, 192, 190,
273193, 194, 193, 187, 178, 169, 164, 169, 177, 181, 181, 182, 175, 161,
150, 144, 138, 129, 121, 117,
274111, 103, 98, 95, 96, 101, 97, 89, 83, 83, 79, 71, 65, 63, 61, 57, 55, 55,
54, 61,
27568, 73, 87, 105, 119, 127, 129, 132, 142, 159, 168, 162, 155, 151, 155,
161, 165, 171, 175, 170,
276162, 156, 151, 152, 161, 167, 170, 179, 188, 191, 197, 200, 195, 185,
178, 179, 181, 185, 188, 182,
277172, 161, 150, 144, 136, 129, 124, 117, 107, 99, 97, 101, 109, 108, 100,
96, 94, 91, 92, 90,
27886, 89, 97, 99, 97, 99, 100, 99, 99, 104, 114, 122, 126, 123, 111, 100,
96, 94, 85, 76,
27975, 77, 79, 90, 108, 117, 124, 129, 129, 128, 128, 129, 128, 129, 137,
136, 119, 100, 90, 88,
28087, 89, 93, 97, 99, 100, 89, 72, 70, 84, 97, 105, 107, 110, 122, 132, 133,
135, 149, 160,
281159, 162, 171, 180, 185, 186, 189, 193, 194, 190, 184, 176, 169, 167,
163, 159, 163, 169, 172, 171,
282165, 153, 148, 149, 139, 129, 122, 114, 109, 106, 106, 113, 112, 102,
93, 89, 93, 100, 100, 97,
28399, 94, 79, 60, 48, 53, 64, 72, 81, 91, 103, 118, 124, 121, 124, 133, 145,
159, 167, 165,
284159, 153, 156, 162, 169, 182, 188, 187, 183, 177, 171, 163, 158, 169,
181, 183, 185, 186, 186, 192,
285194, 188, 183, 183, 182, 180, 176, 168, 160, 161, 156, 142, 139, 135,
123, 125, 127, 121, 114, 104,
28698, 97, 95, 101, 102, 88, 81, 87, 87, 83, 79, 79, 81, 83, 90, 95, 94, 100,
109, 113,
287112, 112, 113, 112, 107, 94, 75, 56, 51, 68, 83, 95, 108, 119, 125, 128,
132, 137, 135, 129,
288125, 131, 137, 127, 109, 102, 93, 78, 80, 95, 106, 113, 111, 99, 85, 78,
81, 89, 94, 96,
289101, 109, 119, 133, 146, 150, 148, 149, 154, 163, 175, 177, 172, 175,
186, 196, 201, 193, 183, 183,
290179, 170, 161, 151, 147, 148, 149, 151, 147, 138, 133, 127, 121, 115,
109, 104, 106, 115, 121, 113,
291102, 98, 101, 106, 104, 103, 105, 104, 104, 100, 87, 69, 57, 58, 68, 76,
92, 110, 113, 112,
292119, 120, 122, 132, 141, 147, 156, 160, 156, 157, 169, 181, 188, 197,
205, 210, 214, 207, 191, 181,
293173, 171, 181, 188, 187, 192, 195, 191, 189, 187, 183, 179, 176, 174,
175, 171, 160, 155, 152, 148,
294143, 137, 136, 141, 148, 144, 127, 114, 111, 110, 111, 109, 104, 97, 84,
76, 83, 85, 75, 76,
29581, 84, 92, 91, 87, 91, 98, 105, 115, 123, 119, 107, 96, 84, 71, 63, 68,
79, 84, 92,
296110, 125, 130, 126, 124, 127, 126, 125, 122, 124, 131, 123, 107, 94, 81,
74, 77, 86, 97, 102,
297103, 101, 94, 82, 75, 74, 79, 88, 100, 114, 121, 125, 132, 135, 134, 142,
150, 158, 167, 169,
298171, 173, 177, 191, 204, 203, 196, 191, 191, 185, 167, 153, 150, 152,
151, 153, 149, 135, 120, 112,
299115, 115, 113, 122, 130, 130, 130, 130, 125, 119, 116, 113, 110, 118,
127, 121, 110, 107, 96, 74,
30067, 73, 73, 76, 89, 99, 98, 92, 96, 108, 109, 106, 115, 127, 135, 144,
154, 159, 156, 163,
301188, 211, 215, 208, 205, 205, 200, 191, 188, 193, 192, 189, 187, 180,
175, 174, 177, 179, 174, 166,
302161, 161, 165, 162, 150, 140, 135, 134, 144, 157, 159, 154, 147, 146,
143, 126, 117, 118, 114, 110,
303107, 99, 82, 70, 72, 71, 63, 61, 69, 83, 89, 85, 86, 85, 80, 86, 104, 113,
105, 91,
30474, 63, 62, 61, 67, 77, 83, 96, 108, 106, 104, 107, 114, 124, 133, 134,
128, 121, 113, 103,
30592, 82, 73, 70, 79, 93, 102, 100, 92, 91, 92, 84, 78, 79, 85, 94, 102, 115,
121, 122,
306135, 145, 137, 132, 141, 151, 160, 171, 178, 183, 187, 193, 207, 219,
218, 212, 202, 194, 189, 175,
307159, 158, 156, 154, 152, 133, 110, 104, 105, 112, 126, 132, 132, 141,
144, 136, 126, 120, 122, 124,
308128, 140, 145, 134, 116, 103, 94, 82, 75, 82, 92, 99, 102, 100, 95, 92,
99, 112, 116, 110,
309109, 118, 126, 132, 142, 153, 163, 180, 199, 210, 211, 210, 212, 213,
212, 203, 193, 190, 191, 193,
310193, 186, 177, 174, 177, 185, 184, 171, 159, 153, 154, 155, 148, 141,
137, 138, 154, 177, 186, 183,
311178, 170, 153, 134, 124, 121, 125, 128, 121, 105, 80, 65, 61, 58, 57, 57,
62, 72, 79, 81,
31278, 73, 74, 85, 99, 102, 90, 72, 61, 59, 59, 59, 68, 81, 94, 95, 83, 87, 98,
105,
313121, 129, 121, 110, 98, 93, 88, 79, 72, 66, 63, 71, 85, 93, 92, 91, 93, 90,
83, 76,
31481, 89, 95, 114, 133, 138, 138, 133, 127, 132, 131, 126, 133, 145, 158,
168, 168, 162, 171, 195,
315219, 230, 226, 217, 207, 198, 190, 174, 158, 155, 159, 162, 151, 131,
116, 110, 118, 140, 153, 149,
316143, 140, 139, 134, 131, 131, 130, 139, 146, 137, 129, 123, 112, 101,
91, 81, 80, 88, 95, 98,
31792, 84, 86, 91, 90, 96, 99, 92, 88, 96, 114, 132, 144, 149, 159, 184, 204,
210, 217, 219,
318213, 204, 192, 183, 182, 188, 198, 205, 205, 198, 191, 184, 178, 175,
170, 156, 145, 143, 145, 143,
319134, 124, 130, 158, 196, 214, 207, 194, 182, 170, 162, 152, 137, 136,
143, 138, 121, 96, 77, 69,
32063, 63, 69, 68, 62, 66, 77, 77, 70, 68, 71, 87, 104, 102, 89, 78, 68, 69,
78, 74,
32171, 80, 85, 86, 92, 98, 106, 114, 113, 109, 107, 104, 99, 97, 91, 80, 71,
66, 65, 76,
32287, 87, 86, 86, 84, 79, 72, 71, 79, 89, 112, 136, 145, 146, 141, 130, 122,
122, 126, 119,
323112, 119, 132, 140, 143, 151, 168, 189, 217, 230, 217, 200, 189, 184,
180, 169, 157, 148, 147, 152,
324150, 140, 133, 134, 141, 152, 159, 155, 149, 151, 154, 149, 141, 137,
142, 149, 151, 143, 132, 126,
325119, 111, 101, 89, 86, 88, 88, 89, 84, 84, 98, 105, 101, 97, 99, 106, 113,
124, 134, 140,
326148, 165, 179, 189, 200, 207, 205, 199, 194, 193, 191, 192, 195, 196,
199, 205, 201, 194, 191, 181,
327165, 158, 158, 153, 143, 132, 126, 127, 133, 146, 166, 181, 199, 212,
200, 177, 161, 155, 154, 149,
328136, 121, 119, 123, 116, 104, 87, 71, 69, 67, 65, 65, 57, 51, 58, 62, 62,
70, 81, 87,
32993, 100, 104, 102, 91, 83, 80, 76, 73, 72, 74, 80, 82, 87, 100, 106, 104,
104, 109, 108,
330100, 93, 84, 70, 64, 67, 70, 66, 67, 70, 70, 68, 61, 55, 60, 79, 97, 99,
105, 119,
331127, 133, 138, 131, 123, 122, 122, 115, 104, 101, 114, 130, 141, 155,
171, 189, 205, 209, 201, 182,
332162, 156, 159, 159, 155, 140, 132, 143, 150, 153, 155, 143, 138, 148,
156, 156, 144, 135, 137, 140,
333142, 146, 147, 152, 158, 152, 136, 121, 110, 101, 93, 85, 81, 75, 66, 71,
81, 87, 100, 109,
334110, 115, 133, 147, 139, 129, 133, 143, 161, 176, 176, 183, 198, 206,
209, 210, 208, 207, 205, 198,
335196, 195, 192, 196, 198, 193, 186, 176, 164, 156, 158, 163, 157, 145,
140, 153, 179, 193, 192, 194,
336205, 211, 200, 181, 168, 157, 147, 139, 129, 120, 117, 117, 107, 90, 82,
79, 72, 68, 64, 56,
33746, 40, 42, 53, 71, 86, 89, 91, 106, 125, 127, 115, 102, 91, 85, 79, 70,
66, 68, 78,
33890, 95, 102, 113, 115, 114, 117, 116, 109, 99, 90, 88, 84, 73, 64, 58, 62,
73, 82, 87,
33982, 73, 79, 88, 86, 84, 90, 101, 109, 107, 105, 115, 121, 121, 126, 128,
119, 112, 119, 139,
340154, 162, 168, 171, 181, 192, 185, 175, 170, 161, 160, 165, 160, 152,
147, 149, 158, 156, 149, 149,
341148, 142, 138, 138, 142, 149, 157, 165, 167, 163, 154, 149, 149, 147,
142, 132, 119, 103, 85, 70,
34265, 64, 63, 72, 87, 90, 93, 106, 119, 133, 138, 137, 141, 142, 144, 152,
159, 167, 171, 174,
343181, 194, 204, 202, 193, 185, 179, 176, 174, 172, 173, 173, 166, 158,
153, 154, 159, 165, 171, 172,
344168, 166, 172, 185, 193, 194, 195, 193, 193, 201, 208, 205, 193, 177,
162, 147, 126, 109, 104, 104,
345101, 90, 74, 67, 67, 62, 55, 50, 51, 67, 87, 96, 103, 102, 96, 98, 106,
116, 125, 121,
346110, 98, 87, 78, 75, 77, 80, 84, 87, 88, 96, 110, 120, 120, 113, 110, 115,
116, 104, 91,
34783, 74, 72, 80, 85, 90, 99, 96, 80, 74, 74, 74, 74, 70, 66, 76, 93, 96, 93,
95,
34898, 105, 113, 117, 124, 131, 131, 137, 147, 152, 157, 163, 171, 184,
196, 196, 187, 179, 174, 169,
349161, 146, 138, 144, 150, 143, 137, 139, 137, 139, 146, 147, 155, 167,
167, 163, 156, 147, 145, 146,
350143, 139, 139, 128, 109, 99, 90, 74, 65, 63, 67, 83, 97, 96, 93, 101, 115,
124, 131, 137,
351150, 164, 169, 174, 178, 172, 167, 164, 165, 180, 194, 189, 179, 174,
165, 157, 155, 153, 145, 147,
352158, 158, 151, 150, 153, 164, 170, 165, 171, 185, 187, 187, 192, 195,
193, 193, 206, 220, 223, 210,
353187, 169, 153, 132, 114, 98, 82, 79, 84, 76, 61, 54, 50, 51, 59, 62, 76,
100, 114, 114,
354105, 100, 101, 104, 105, 104, 111, 113, 104, 99, 94, 82, 71, 63, 57, 59,
73, 86, 92, 96,
35599, 102, 104, 105, 112, 120, 116, 107, 96, 85, 79, 77, 84, 89, 88, 88, 84,
75, 68, 67,
35666, 65, 67, 74, 93, 104, 91, 81, 79, 85, 101, 110, 121, 138, 147, 150,
155, 159, 165, 178,
357188, 192, 196, 196, 189, 187, 182, 170, 157, 147, 142, 144, 156, 161,
157, 155, 155, 156, 159, 154,
358152, 162, 175, 178, 174, 165, 159, 152, 141, 138, 144, 148, 141, 123,
104, 89, 73, 66, 73, 83,
35997, 112, 113, 109, 110, 116, 127, 145, 164, 177, 184, 184, 179, 171,
160, 153, 160, 170, 173, 177,
360175, 162, 157, 163, 161, 155, 153, 153, 159, 159, 147, 145, 153, 157,
156, 157, 164, 173, 182, 195,
361205, 207, 209, 215, 219, 211, 201, 197, 185, 169, 153, 129, 104, 85, 77,
80, 86, 88, 79, 65,
36255, 50, 47, 54, 76, 102, 115, 116, 111, 106, 103, 99, 93, 92, 100, 105,
99, 92, 79, 62,
36353, 49, 52, 62, 74, 86, 86, 81, 85, 94, 101, 106, 108, 108, 105, 101, 96,
92, 89, 84,
36479, 82, 89, 89, 84, 78, 70, 66, 63, 58, 63, 72, 77, 79, 74, 71, 76, 86, 95,
98,
365105, 123, 144, 164, 179, 181, 183, 187, 181, 178, 180, 184, 191, 188,
174, 167, 161, 155, 153, 153,
366160, 168, 163, 157, 154, 150, 145, 137, 139, 156, 175, 182, 178, 171,
167, 162, 160, 156, 150, 149,
367144, 130, 110, 95, 88, 88, 94, 100, 116, 133, 127, 115, 114, 121, 133,
143, 153, 168, 180, 185,
368178, 169, 167, 164, 163, 167, 166, 170, 180, 180, 179, 184, 185, 176,
165, 153, 150, 158, 159, 154,
369153, 158, 162, 156, 151, 163, 181, 201, 217, 225, 226, 221, 210, 199,
187, 180, 174, 161, 141, 119,
370103, 93, 87, 84, 84, 84, 76, 60, 44, 33, 30, 30, 45, 74, 98, 113, 113, 98,
89, 89,
37192, 95, 93, 90, 88, 81, 73, 71, 72, 72, 75, 78, 75, 78, 87, 92, 95, 103,
106, 99,
37291, 95, 98, 94, 96, 97, 97, 98, 101, 102, 94, 86, 82, 78, 79, 81, 77, 69,
65, 65,
37369, 76, 81, 84, 84, 86, 95, 98, 103, 127, 153, 169, 186, 196, 194, 189,
183, 175, 171, 179,
374184, 181, 181, 180, 169, 157, 153, 156, 155, 151, 149, 150, 146, 141,
137, 129, 125, 140, 154, 161,
375169, 172, 176, 185, 183, 173, 160, 145, 132, 121, 111, 107, 104, 103,
113, 126, 125, 115, 108, 103,
376106, 115, 123, 131, 141, 153, 161, 164, 167, 168, 164, 161, 166, 174,
179, 184, 193, 193, 190, 193,
377190, 175, 159, 148, 142, 147, 160, 168, 170, 165, 155, 143, 143, 161,
172, 182, 210, 227, 220, 213,
378211, 206, 193, 181, 171, 157, 147, 138, 126, 116, 104, 87, 76, 68, 62,
53, 42, 33, 30, 34,
37953, 84, 101, 98, 92, 88, 85, 91, 103, 105, 95, 86, 80, 83, 85, 81, 75, 74,
81, 91,
38090, 88, 93, 96, 96, 98, 100, 95, 91, 95, 93, 86, 93, 101, 105, 113, 115,
112, 103, 87,
38179, 81, 79, 76, 72, 61, 56, 58, 64, 71, 74, 74, 76, 80, 85, 94, 114, 140,
148, 146,
382165, 187, 187, 182, 184, 186, 187, 191, 200, 201, 186, 173, 169, 161,
156, 155, 151, 149, 153, 152,
383146, 141, 133, 123, 122, 138, 157, 162, 168, 182, 188, 184, 182, 179,
165, 144, 133, 134, 127, 119,
384119, 121, 128, 126, 113, 103, 93, 86, 87, 99, 117, 127, 138, 154, 156,
145, 141, 147, 157, 167,
385179, 190, 193, 193, 193, 189, 181, 175, 170, 160, 151, 142, 134, 137,
153, 165, 158, 148, 145, 137,
386132, 145, 160, 172, 194, 213, 219, 217, 211, 202, 189, 179, 180, 181,
170, 156, 140, 122, 105, 87,
38767, 58, 57, 44, 29, 27, 31, 37, 52, 75, 85, 81, 85, 91, 92, 96, 106, 112,
102, 92,
38898, 102, 93, 84, 83, 90, 99, 110, 119, 115, 106, 100, 91, 83, 87, 93, 93,
96, 97, 96,
389102, 108, 110, 114, 115, 116, 113, 101, 97, 101, 92, 83, 77, 68, 63, 66,
67, 68, 73, 76,
39073, 75, 86, 94, 102, 117, 128, 137, 162, 188, 196, 195, 192, 191, 190,
185, 189, 193, 185, 178,
391170, 158, 152, 151, 151, 150, 149, 145, 139, 133, 129, 130, 136, 148,
162, 172, 181, 185, 185, 185,
392183, 181, 174, 158, 150, 147, 135, 124, 118, 114, 115, 118, 115, 104,
90, 78, 72, 80, 98, 111,
393125, 140, 144, 144, 155, 168, 175, 184, 193, 199, 202, 199, 199, 198,
188, 178, 173, 164, 153, 145,
394144, 149, 153, 155, 154, 150, 144, 134, 128, 136, 151, 169, 198, 221,
226, 224, 212, 198, 192, 190,
395195, 201, 190, 167, 142, 120, 101, 84, 73, 66, 55, 39, 29, 31, 36, 39, 46,
63, 78, 89,
39696, 98, 100, 102, 104, 107, 104, 102, 107, 103, 90, 82, 84, 90, 103, 115,
114, 108, 96, 84,
39782, 75, 70, 74, 80, 85, 88, 96, 112, 119, 120, 123, 120, 114, 108, 104,
107, 106, 94, 78,
39865, 64, 66, 62, 62, 64, 63, 64, 65, 65, 63, 58, 68, 89, 103, 116, 146, 179,
189, 185,
399184, 186, 184, 186, 192, 193, 187, 172, 157, 154, 152, 147, 145, 144,
141, 138, 137, 137, 132, 127,
400137, 155, 163, 167, 176, 186, 183, 175, 171, 164, 158, 155, 151, 150,
146, 135, 121, 112, 114, 117,
401111, 98, 85, 77, 75, 74, 79, 90, 105, 123, 136, 147, 162, 179, 193, 199,
200, 199, 199, 200,
402200, 200, 194, 184, 173, 164, 155, 151, 155, 156, 145, 141, 148, 144,
129, 115, 118, 131, 137, 156,
403195, 222, 226, 222, 211, 200, 201, 208, 214, 212, 197, 176, 153, 128,
102, 82, 70, 64, 53, 40,
40439, 43, 41, 37, 41, 57, 75, 87, 90, 96, 109, 113, 107, 105, 108, 112, 113,
114, 111, 105,
405101, 104, 117, 120, 113, 109, 96, 78, 72, 72, 71, 73, 73, 75, 90, 109,
120, 124, 126, 128,
406121, 107, 102, 108, 111, 109, 105, 95, 79, 68, 65, 62, 61, 60, 60, 63, 62,
56, 52, 50,
40753, 65, 83, 108, 140, 167, 180, 192, 201, 194, 189, 194, 200, 204, 196,
179, 168, 161, 157, 151,
408144, 145, 144, 140, 145, 154, 156, 154, 157, 163, 166, 175, 184, 188,
190, 185, 174, 162, 157, 159,
409165, 172, 170, 157, 138, 122, 123, 123, 107, 95, 92, 83, 73, 71, 80, 89,
97, 114, 140, 164,
410178, 186, 196, 203, 200, 196, 198, 199, 195, 194, 196, 191, 182, 174,
173, 170, 161, 152, 140, 126,
411119, 117, 116, 115, 114, 118, 127, 144, 177, 207, 220, 228, 226, 212,
206, 212, 212, 205, 193, 169,
412145, 126, 103, 81, 64, 53, 49, 51, 51, 46, 43, 37, 38, 48, 57, 68, 84, 94,
99, 100,
41396, 96, 105, 115, 127, 138, 136, 129, 125, 123, 123, 120, 110, 97, 83,
71, 62, 60, 63, 70,
41485, 96, 99, 105, 112, 115, 115, 106, 95, 96, 102, 102, 102, 103, 100, 89,
79, 75, 66, 56,
41553, 51, 47, 39, 35, 35, 36, 39, 50, 61, 72, 96, 130, 161, 184, 197, 198,
194, 191, 186,
416183, 185, 186, 183, 181, 175, 165, 156, 155, 158, 159, 162, 166, 167,
165, 163, 165, 166, 165, 172,
417181, 175, 168, 165, 159, 156, 161, 171, 178, 178, 172, 157, 140, 131,
123, 113, 109, 106, 92, 78,
41870, 70, 82, 104, 126, 139, 145, 156, 172, 181, 185, 185, 188, 192, 191,
189, 187, 183, 184, 185,
419188, 193, 189, 169, 145, 127, 113, 102, 100, 109, 115, 115, 120, 130,
140, 158, 184, 207, 225, 233,
420233, 227, 214, 200, 192, 189, 176, 155, 135, 115, 95, 78, 64, 59, 61, 54,
44, 41, 40, 40,
42143, 46, 51, 64, 81, 91, 97, 101, 106, 112, 122, 133, 137, 137, 133, 128,
131, 130, 126, 124,
422113, 96, 81, 63, 49, 49, 60, 80, 99, 104, 98, 93, 95, 96, 91, 91, 101, 110,
116, 119,
423116, 110, 101, 96, 96, 95, 86, 68, 52, 43, 38, 35, 33, 31, 36, 46, 55, 67,
75, 83,
424110, 144, 163, 174, 181, 178, 176, 172, 165, 169, 176, 178, 182, 184,
182, 176, 169, 168, 173, 174,
425171, 169, 167, 165, 172, 178, 169, 165, 170, 169, 161, 157, 157, 159,
167, 174, 172, 159, 150, 148,
426143, 132, 129, 135, 133, 122, 114, 104, 86, 85, 100, 117, 136, 148, 146,
147, 158, 168, 179, 186,
427186, 188, 194, 193, 184, 179, 186, 197, 198, 193, 189, 173, 146, 123,
107, 96, 96, 112, 131, 142,
428151, 160, 153, 147, 162, 185, 207, 218, 217, 207, 196, 185, 170, 154,
143, 131, 116, 103, 94, 84,
42975, 70, 64, 53, 44, 44, 51, 53, 56, 62, 65, 75, 92, 103, 105, 102, 103,
106, 110, 119,
430123, 117, 117, 120, 116, 111, 116, 116, 104, 90, 74, 53, 41, 46, 61, 74,
87, 97, 92, 83,
43184, 91, 99, 109, 120, 127, 130, 127, 118, 114, 113, 108, 100, 94, 88, 75,
58, 46, 39, 31,
43224, 35, 54, 62, 71, 83, 83, 87, 116, 148, 164, 176, 181, 173, 168, 168,
167, 173, 188, 196,
433191, 185, 187, 195, 196, 189, 185, 179, 174, 177, 184, 190, 193, 189,
172, 156, 157, 161, 157, 155,
434155, 151, 150, 150, 149, 148, 145, 138, 131, 130, 138, 149, 151, 139,
122, 106, 97, 103, 110, 115,
435130, 147, 145, 141, 158, 183, 188, 183, 177, 171, 172, 175, 177, 185,
190, 189, 184, 178, 174, 166,
436151, 133, 123, 124, 130, 143, 159, 168, 171, 170, 164, 157, 162, 183,
203, 207, 202, 191, 179, 169,
437151, 134, 125, 111, 93, 85, 84, 83, 78, 69, 60, 57, 60, 62, 61, 63, 74, 83,
88, 92,
43897, 108, 113, 106, 100, 99, 95, 97, 108, 113, 111, 110, 106, 96, 89, 89,
84, 70, 58, 49,
43945, 53, 60, 68, 84, 93, 95, 97, 100, 108, 116, 119, 121, 123, 121, 114,
108, 111, 111, 99,
44085, 75, 72, 70, 61, 50, 40, 30, 30, 38, 46, 58, 73, 82, 91, 103, 119, 143,
161, 165,
441167, 171, 169, 163, 168, 179, 184, 186, 183, 176, 178, 181, 176, 172,
178, 185, 185, 181, 181, 187,
442191, 188, 181, 170, 163, 162, 159, 160, 163, 154, 139, 127, 130, 142,
149, 146, 138, 134, 139, 146,
443145, 134, 128, 126, 123, 118, 115, 122, 142, 157, 163, 166, 171, 178,
181, 178, 173, 172, 172, 167,
444170, 185, 188, 173, 158, 152, 155, 157, 151, 140, 133, 134, 141, 144,
145, 155, 175, 187, 186, 177,
445177, 189, 196, 193, 190, 183, 167, 146, 127, 115, 110, 107, 98, 90, 87,
82, 71, 64, 66, 75,
44683, 81, 79, 83, 93, 107, 114, 106, 100, 107, 110, 109, 110, 106, 101, 96,
92, 96, 99, 91,
44780, 71, 63, 61, 63, 61, 59, 60, 61, 57, 52, 61, 88, 116, 126, 121, 115,
118, 123, 130,
448136, 131, 123, 120, 114, 111, 109, 98, 85, 77, 72, 65, 54, 43, 34, 28, 28,
35, 45, 63,
44987, 105, 113, 112, 117, 141, 164, 170, 171, 169, 162, 161, 164, 164,
166, 168, 169, 169, 168, 166,
450164, 167, 175, 178, 173, 172, 174, 181, 192, 190, 180, 172, 167, 164,
158, 154, 151, 145, 139, 131,
451129, 134, 132, 124, 128, 136, 135, 136, 137, 129, 125, 131, 137, 138,
132, 133, 154, 172, 172, 169,
452172, 174, 174, 180, 185, 186, 187, 184, 180, 183, 181, 171, 167, 164,
159, 154, 144, 134, 136, 140,
453138, 140, 142, 151, 178, 194, 191, 185, 180, 186, 194, 189, 181, 171,
155, 137, 123, 116, 112, 112,
454111, 102, 93, 85, 77, 72, 71, 78, 86, 84, 86, 104, 121, 123, 113, 100, 94,
98, 105, 107,
455105, 100, 96, 93, 86, 79, 78, 72, 58, 52, 54, 57, 65, 69, 65, 62, 60, 60,
62, 70,
45692, 112, 111, 106, 114, 126, 131, 130, 130, 128, 123, 121, 121, 122,
119, 110, 99, 85, 72, 63,
45754, 44, 34, 27, 31, 43, 57, 71, 94, 112, 112, 109, 111, 128, 147, 148,
147, 153, 155, 154,
458150, 150, 154, 157, 157, 160, 167, 168, 166, 171, 176, 171, 163, 161,
167, 178, 193, 196, 184, 175,
459166, 163, 166, 162, 156, 149, 137, 126, 121, 125, 132, 138, 137, 132,
132, 137, 144, 146, 139, 138,
460143, 146, 148, 150, 157, 167, 164, 158, 159, 166, 176, 182, 188, 193,
196, 198, 198, 197, 195, 184,
461169, 160, 155, 149, 151, 156, 150, 140, 137, 138, 142, 147, 164, 183,
187, 181, 173, 169, 171, 165,
462153, 148, 142, 130, 118, 112, 116, 119, 115, 111, 108, 99, 87, 80, 78,
80, 84, 98, 114, 120,
463125, 125, 113, 103, 98, 94, 102, 107, 102, 102, 103, 94, 78, 66, 67, 70,
66, 61, 55, 56,
46470, 80, 80, 76, 67, 62, 58, 53, 69, 92, 101, 113, 123, 122, 123, 127, 131,
133, 133, 132,
465129, 130, 130, 123, 109, 92, 76, 63, 55, 52, 48, 43, 46, 60, 71, 76, 95,
110, 105, 95,
46689, 94, 112, 120, 124, 137, 146, 144, 137, 133, 139, 146, 153, 160, 167,
169, 166, 165, 171, 170,
467164, 166, 170, 172, 176, 181, 181, 177, 171, 165, 163, 157, 145, 134,
132, 133, 125, 119, 131, 145,
468145, 142, 142, 139, 139, 145, 150, 152, 155, 161, 159, 152, 156, 167,
173, 175, 174, 170, 175, 181,
469185, 191, 199, 205, 203, 191, 182, 177, 172, 169, 164, 161, 165, 167,
163, 156, 154, 158, 157, 154,
470158, 168, 175, 172, 163, 155, 156, 158, 151, 145, 143, 137, 127, 119,
115, 117, 125, 127, 113, 96,
47184, 81, 85, 88, 98, 123, 133, 125, 125, 128, 121, 111, 98, 90, 92, 94, 92,
87, 87, 91,
47285, 73, 66, 61, 61, 60, 55, 50, 49, 58, 66, 61, 51, 46, 46, 47, 54, 74, 99,
115,
473116, 116, 120, 121, 119, 120, 124, 130, 132, 127, 117, 108, 108, 107,
93, 77, 65, 61, 59, 54,
47459, 75, 83, 85, 91, 96, 94, 92, 91, 88, 93, 115, 134, 135, 131, 136, 142,
141, 138, 140,
475149, 158, 161, 158, 153, 159, 171, 169, 166, 174, 178, 172, 171, 174,
177, 177, 168, 156, 147, 137,
476131, 130, 126, 128, 137, 143, 138, 132, 135, 141, 141, 133, 131, 138,
145, 148, 150, 156, 165, 169,
477169, 174, 181, 185, 184, 175, 169, 175, 182, 184, 185, 189, 191, 186,
178, 171, 167, 171, 176, 176,
478171, 173, 179, 175, 172, 176, 173, 170, 172, 174, 176, 181, 182, 173,
162, 156, 154, 154, 145, 134,
479134, 134, 128, 119, 115, 114, 106, 96, 89, 85, 87, 98, 117, 135, 139,
134, 134, 135, 135, 127,
480112, 102, 95, 94, 99, 101, 97, 95, 95, 90, 82, 68, 52, 46, 45, 40, 35, 42,
50, 47,
48144, 47, 45, 46, 65, 91, 106, 115, 124, 123, 117, 115, 118, 117, 122, 126,
122, 120, 122, 119,
482110, 100, 90, 78, 68, 63, 57, 53, 62, 79, 86, 87, 93, 97, 96, 93, 88, 86,
93, 112,
483130, 130, 126, 129, 136, 143, 148, 147, 144, 143, 142, 150, 159, 162,
168, 170, 171, 174, 174, 170,
484169, 174, 178, 177, 175, 167, 152, 145, 141, 130, 133, 148, 156, 155,
151, 141, 134, 134, 129, 121,
485121, 127, 130, 136, 149, 166, 178, 184, 193, 195, 192, 191, 184, 174,
172, 175, 180, 183, 184, 181,
486178, 179, 172, 163, 163, 170, 172, 169, 168, 172, 171, 168, 167, 169,
167, 162, 162, 165, 170, 174,
487174, 168, 155, 145, 141, 137, 126, 115, 117, 125, 125, 118, 108, 100,
91, 79, 74, 79, 90, 109,
488128, 140, 146, 149, 153, 147, 134, 127, 118, 107, 105, 109, 112, 107,
98, 96, 94, 84, 72, 57,
48943, 36, 30, 22, 21, 25, 30, 40, 46, 42, 48, 70, 91, 104, 113, 126, 136,
132, 128, 127,
490126, 126, 126, 129, 137, 138, 132, 125, 113, 102, 92, 77, 67, 57, 52, 62,
72, 80, 89, 90,
49193, 95, 87, 89, 99, 99, 98, 110, 123, 129, 127, 125, 127, 133, 137, 137,
140, 148, 151, 152,
492156, 157, 158, 165, 172, 172, 166, 162, 166, 170, 166, 162, 162, 157,
152, 149, 145, 146, 147, 152,
493162, 164, 157, 150, 140, 129, 120, 112, 105, 108, 123, 145, 163, 170,
177, 186, 192, 195, 192, 189,
494187, 182, 181, 181, 181, 188, 191, 189, 189, 182, 173, 174, 176, 176,
177, 178, 174, 165, 160, 163,
495167, 164, 158, 157, 162, 165, 160, 155, 153, 142, 133, 137, 140, 132,
124, 116, 110, 109, 108, 106,
496102, 97, 91, 87, 83, 85, 94, 114, 135, 145, 146, 144, 142, 140, 130, 119,
115, 113, 112, 109,
497106, 108, 103, 91, 87, 80, 67, 54, 42, 29, 18, 9, 5, 13, 27, 38, 48, 54, 56,
68,
49891, 110, 117, 119, 121, 123, 129, 134, 135, 138, 144, 144, 144, 142,
133, 120, 105, 92, 83, 72,
49962, 58, 57, 61, 70, 78, 83, 92, 99, 101, 104, 107, 106, 107, 111, 119,
129, 135, 135, 131,
500129, 132, 133, 134, 136, 142, 149, 150, 149, 150, 153, 161, 169, 169,
163, 157, 157, 159, 156, 152,
501155, 160, 161, 164, 169, 170, 172, 172, 173, 173, 166, 152, 137, 128,
119, 109, 109, 121, 134, 145,
502156, 160, 161, 166, 174, 184, 191, 189, 186, 185, 178, 173, 182, 193,
203, 204, 198, 197, 196, 192,
503187, 182, 180, 177, 175, 173, 168, 166, 169, 171, 170, 169, 168, 165,
154, 143, 134, 128, 126, 130,
504133, 130, 124, 113, 101, 101, 102, 98, 98, 98, 97, 96, 99, 104, 108, 119,
131, 134, 132, 130,
505132, 135, 131, 123, 121, 121, 117, 110, 105, 99, 95, 89, 85, 81, 69, 55,
43, 29, 17, 12,
50616, 26, 33, 42, 55, 61, 67, 77, 91, 107, 118, 120, 125, 128, 130, 134,
140, 145, 146, 143,
507142, 136, 124, 111, 96, 80, 69, 62, 59, 57, 52, 50, 56, 65, 74, 86, 96,
109, 116,
508};
Rick Roll
The following example was created by Samantha Lagestee in 2017. Inspired
by the popular meme, this code rickrolls people by playing the song "Never
Gonna Give You Up" by Rick Astley on a piezo buzzer. Open the serial port
to see the lyrics and sing along.
Code
Copy
10 DISCLAIMER: The song "Never Gonna Give You Up" by Rick Astley
13
14*/
15
32
33#define rest -1
34
36int piezo = 8;
37int led = 9;
38
41
45
47
50int song1_intro_melody[] =
51{c5s, e5f, e5f, f5, a5f, f5s, f5, e5f, c5s, e5f, rest, a4f, a4f};
52
53int song1_intro_rhythmn[] =
55
57
58int song1_verse1_melody[] =
59{ rest, c4s, c4s, c4s, c4s, e4f, rest, c4, b3f, a3f,
61rest, b3f, b3f, c4, c4s, b3f, c4s, e4f, rest, c4, b3f, b3f, a3f,
62rest, b3f, b3f, c4, c4s, a3f, a3f, e4f, e4f, e4f, f4, e4f,
63c4s, e4f, f4, c4s, e4f, e4f, e4f, f4, e4f, a3f,
65};
66
67int song1_verse1_rhythmn[] =
68{ 2, 1, 1, 1, 1, 2, 1, 1, 1, 5,
691, 1, 1, 1, 3, 1, 2, 1, 5,
701, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3,
711, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4,
725, 1, 1, 1, 1, 1, 1, 1, 2, 2,
732, 1, 1, 1, 3, 1, 1, 1, 3
74};
75
76char\* lyrics_verse1[] =
77{ "We're ", "no ", "strangers ", "", "to ", "love ", "", "\r\n",
78"You ", "know ", "the ", "rules ", "and ", "so ", "do ", "I\r\n",
79"A ", "full ", "commitment's ", "", "", "what ", "I'm ", "thinking ", "", "of", "\r\
n",
80"You ", "wouldn't ", "", "get ", "this ", "from ", "any ", "", "other ", "", "guy\r\
n",
81"I ", "just ", "wanna ", "", "tell ", "you ", "how ", "I'm ", "feeling", "\r\n",
82"Gotta ", "", "make ", "you ", "understand", "", "\r\n"
83};
84
86
87int song1_chorus_melody[] =
89f5, f5, e5f, b4f, b4f, a4f, a4f, e5f, e5f, c5s, c5, b4f,
93f5, f5, e5f, b4f, b4f, a4f, a4f, a5f, c5, c5s, c5, b4f,
95c5s, e5f, c5, b4f, a4f, rest, a4f, e5f, c5s, rest
96};
97
98int song1_chorus_rhythmn[] =
99{ 1, 1, 1, 1,
1003, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
1011, 1, 1, 1,
1023, 3, 3, 1, 2, 2, 2, 4, 8,
1031, 1, 1, 1,
1043, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
1051, 1, 1, 1,
1063, 3, 3, 1, 2, 2, 2, 4, 8, 4
107};
108
109char* lyrics_chorus[] =
110{ "Never ", "", "gonna ", "", "give ", "you ", "up\r\n",
111"Never ", "", "gonna ", "", "let ", "you ", "down", "", "\r\n",
112"Never ", "", "gonna ", "", "run ", "around ", "", "", "", "and ", "desert ", "",
"you\r\n",
113"Never ", "", "gonna ", "", "make ", "you ", "cry\r\n",
114"Never ", "", "gonna ", "", "say ", "goodbye ", "", "", "\r\n",
115"Never ", "", "gonna ", "", "tell ", "a ", "lie ", "", "", "and ", "hurt ", "you\r\
n"
116};
117
118void setup()
119{
123 Serial.begin(9600);
125 a = 4;
126 b = 0;
127 c = 0;
128}
129
130void loop()
131{
133 /*
136 }
139 }
140 */
141
144 play();
145 }
146}
147
148void play() {
150 if (a == 1 || a == 2) { // Intro
151 // intro
156 }
157
158 b++;
160 a++;
161 b = 0;
162 c = 0;
163 }
165 // verse
169 Serial.print(lyrics_verse1[c]);
171 c++;
172 }
173 b++;
175 a++;
176 b = 0;
177 c = 0;
178 }
180 // chorus
184 Serial.print(lyrics_chorus[c]);
186 c++;
187 }
188
189 b++;
191 Serial.println("");
192 a++;
193 b = 0;
194 c = 0;
195 }
196 }
197
199 noTone(piezo);
203 a = 1;
204 }
205}
MusicalAlgoFun
This is a simple song with the Arduino created by Alexandre Quessy in
2006.
Code
Copy
1/\*
5- operation:
6-
10 \*/
11
12int ledPin = 9;
13int speakerOut = 8;
14
16/_ MIDI notes from 48 to 71. Indices here are from 0 to 23. _/
17
23
26// do do do re mi re do mi re re do...
27
28byte beat = 0;
32byte period = 0;
33int i, timeUp;
34
35void setup() {
36pinMode(ledPin, OUTPUT);
37pinMode(speakerOut, OUTPUT);
38}
39
40void loop() {
41digitalWrite(speakerOut, LOW);
43statePin = !statePin;
44digitalWrite(ledPin, statePin);
45
46 timeUp = timeUpDown[song[beat]];
47
50 digitalWrite(speakerOut, HIGH);
51 delayMicroseconds(timeUp);
52 digitalWrite(speakerOut, LOW);
53 delayMicroseconds(timeUp);
54 }
56 /* delay(50); */
57
58}
59digitalWrite(speakerOut, LOW);
60delay(1000);
61}
Improved version
Copy
1/\*
5- operation:
6-
10 \*/
11
14
20
21/_ our song. Each number pair is a MIDI note and a note symbol. _/
22/_ Symbols are 1 for whole, -1 for dotted whole, 2 for half, _/
23/_ -2 for dotted half, 4 for quarter, -4 for dotted quarter, etc. _/
24
2764,4,64,4,65,4,67,4, 67,4,65,4,64,4,62,4,
2860,4,60,4,62,4,64,4, 64,-4,62,8,62,2,
2964,4,64,4,65,4,67,4, 67,4,65,4,64,4,62,4,
AuthorDon Cross
Last revision10/28/2024
In the familiar decimal system (base ten), a number like 572 means
5*10^2 + 7*10^1 + 2*10^0. Likewise, in binary a number like 11010
means 1*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0 \= 16 + 8 + 2 = 26.
It is crucial that you understand how the binary system works in order to
follow the remainder of this tutorial. If you need help in this area, one good
place to start is the Wikipedia article on the binary system .
0b
, e.g.,
0b11 == 3
. For legacy reasons, it also defines the constants
B0
through
B11111111
, which can be used in the same way.
Bitwise AND
The bitwise AND operator in C++ is a single ampersand,
&
, used between two other integer expressions. Bitwise AND operates on each
bit position of the surrounding expressions independently, according to this
rule: if both input bits are 1, the resulting output is 1, otherwise the output is
0. Another way of expressing this is:
Copy
10 & 0 == 0
2 0 & 1 == 0
3 1 & 0 == 0
4 1 & 1 == 1
int
is a 16-bit value, so using
&
between two
int
expressions causes 16 simultaneous AND operations to occur. In a code
fragment like:
Copy
a
and
b
are processed by using the bitwise AND, and all 16 resulting bits are stored
in
c
, resulting in the value
01000100
in binary, which is 68 in decimal.
One of the most common uses of bitwise AND is to select a particular bit (or
bits) from an integer value, often called masking. For example, if you
wanted to access the least significant bit in a variable
x
, and store the bit in another variable
y
, you could use the following code:
Copy
3 x = 4; // binary: 100
4 y = x & 1; // now y == 0
Bitwise OR
The bitwise OR operator in C++ is the vertical bar symbol,
|
. Like the
&
operator,
|
operates independently each bit in its two surrounding integer expressions,
but what it does is different (of course). The bitwise OR of two bits is 1 if
either or both of the input bits is 1, otherwise it is 0. In other words:
Copy
10 | 0 == 0
2 0 | 1 == 1
3 1 | 0 == 1
4 1 | 1 == 1
Bitwise OR is often used to make sure that a given bit is turned on (set to 1)
in a given expression. For example, to copy the bits from
a
into
b
, while making sure the lowest bit is set to 1, use the following code:
Copy
1b = a | 1;
Bitwise XOR
There is a somewhat unusual operator in C++ called bitwise exclusive OR,
also known as bitwise XOR. (In English this is usually pronounced "eks-or".)
The bitwise XOR operator is written using the caret symbol
^
. This operator is similar to the bitwise OR operator
|
, except that it evaluates to 1 for a given position when exactly one of the
input bits for that position is 1. If both are 0 or both are 1, the XOR operator
evaluates to 0 :
Copy
10 ^ 0 == 0
2 0 ^ 1 == 1
3 1 ^ 0 == 1
4 1 ^ 1 == 0
Another way to look at bitwise XOR is that each bit in the result is a 1 if the
input bits are different, or 0 if they are the same.
Copy
The
^
operator is often used to toggle (i.e. change from 0 to 1, or 1 to 0) some of
the bits in an integer expression while leaving others alone. For example:
Copy
Bitwise NOT
The bitwise NOT operator in C++ is the tilde character
~
. Unlike
&
and
|
, the bitwise NOT operator is applied to a single operand to its right. Bitwise
NOT changes each bit to its opposite: 0 becomes 1, and 1 becomes 0. For
example:
Copy
You might be surprised to see a negative number like -104 as the result of
this operation. This is because the highest bit in an
int
variable is the so-called sign bit. If the highest bit is 1, the number is
interpreted as negative. This encoding of positive and negative numbers is
referred to as two's complement. For more information, see the Wikipedia
article on two's complement .
As an aside, it is interesting to note that for any integer
x
,
~x
is the same as
-x-1
.
At times, the sign bit in a signed integer expression can cause some
unwanted surprises, as we shall see later.
<<
and the right shift operator
>>
. These operators cause the bits in the left operand to be shifted left or right
by the number of positions specified by the right operand. For example:
Copy
x
by
y
bits (
x << y
), the leftmost
y
bits in
x
are lost, literally shifted out of existence:
Copy
If you are certain that none of the ones in a value are being shifted into
oblivion, a simple way to think of the left-shift operator is that it multiplies
the left operand by 2 raised to the right operand power. For example, to
generate powers of 2, the following expressions can be employed:
Copy
11 << 0 == 1
2 1 << 1 == 2
3 1 << 2 == 4
4 1 << 3 == 8
5 ...
6 1 << 8 == 256
7 1 << 9 == 512
8 1 << 10 == 1024
9 ...
x
right by
y
bits (
x >> y
), and the highest bit in
x
is a 1, the behavior depends on the exact data type of
x
. If
x
is of type
int
, the highest bit is the sign bit, determining whether
x
is negative or not, as we have discussed above. In that case, the sign bit is
copied into lower bits, for esoteric historical reasons:
Copy
This behavior, called sign extension, is often not the behavior you want.
Instead, you may wish zeros to be shifted in from the left. It turns out that
the right shift rules are different for
unsigned int
expressions, so you can use a typecast to suppress ones being copied from
the left:
Copy
If you are careful to avoid sign extension, you can use the right-shift
operator
>>
as a way to divide by powers of 2. For example:
Copy
1int x = 1000;
Assignment Operators
Often in programming, you want to operate on the value of a variable
x
and store the modified value back into
x
. In most programming languages, for example, you can increase the value
of a variable
x
by 7 using the following code:
Copy
1x = x + 7; // increase x by 7
Copy
1x += 7; // increase x by 7
It turns out that bitwise AND, bitwise OR, left shift, and right shift, all have
shorthand assignment operators. Here is an example:
Copy
~
; if you want to toggle all the bits in
x
, you need to do this:
Copy
&
is not the same as the boolean AND operator
&&
, for two reasons:
&
&&
true
\==1 or
false
true
or
false
4 & 2 == 0
, because 4 is 100 in binary and 2 is 010 in binary, and none of the bits
are 1 in both integers. However,
4 && 2 == true
, and
true
numerically is equal to
true
values.
Copy
2 {
5 return x;
6 }
Copy
1void setup()
2 {
3 Serial.begin (9600);
4 }
Copy
1void loop()
2 {
5 }
If you compile and upload this program, and then monitor the serial output
from the Arduino GUI, you will see the following lines of text repeated every
second:
Copy
1fred 0
2 fred 1
fred(0)
and
fred(1)
are called, resulting in the generated output, the return values 0 and 1 are
bitwise-ANDed together, storing 0 in
x
. If you edit the line
Copy
&
with its boolean counterpart
&&
,
Copy
Copy
1fred 0
&&
is using a short-cut: if its left operand is zero (a.k.a.
false
), it is already certain that the result of the expression will be
false
, so there is no need to evaluate the right operand. In other words, the line of
code
int x = fred(0) && fred(1);
is identical in meaning to:
Copy
1int x;
2 if (fred(0) == 0) {
3 x = false; // stores 0 in x
4 } else {
5 if (fred(1) == 0) {
6 x = false; // stores 0 in x
7 } else {
8 x = true; // stores 1 in x
9 }
10 }
&&
is a lot more concise way to express this surprisingly complex piece of logic.
As with bitwise AND and boolean AND, there are differences between
bitwise OR and boolean OR. The bitwise OR operator
|
always evaluates both of its operands, whereas the boolean OR operator
||
evaluates its right operand only if its left operand is
false
(zero). Also, bitwise
|
operates independently on all of the bits in its operands, whereas boolean
||
treats both of its operands as either true (nonzero) or false (zero), and
evaluates to either true (if either operand is nonzero) or false (if both
operands are zero).
Usually when you want to read or write to digital pins in the Atmega8, you
use the built-in functions digitalRead() or digitalWrite() supplied by the
Arduino environment. Suppose that in your
setup()
function, you wanted to define the digital pins 2 through 13 as output, and
then you wanted pins 11, 12, and 13 to be set HIGH, and all the other pins
set LOW. Here is how one would typically accomplish this:
Copy
1void setup()
2 {
3 int pin;
6 }
9 }
12 }
13 }
It turns out there is a way to accomplish the same thing using direct access
to Atmega8 hardware ports and bitwise operators:
Copy
1void setup()
2 {
Copy
Copy
2 PORTD &= B00000011; // turns off 2..7, but leaves pins 0 and 1 alone
Copy
1// Write simultaneously to pins 8..13...
3 }
This code takes advantage of the fact that the control registers
DDRD
and
DDRB
each contain 8 bits that determine whether a given digital pin is output (1)
or input (0). The upper 2 bits in DDRB are not used, because there is no such
thing is digital pin 14 or 15 on the Atmega8. Likewise, the port registers
PORTB
and
PORTD
contain one bit for the most recently written value to each digital pin, HIGH
(1) or LOW (0).
Generally speaking, doing this sort of thing is not a good idea. Why not?
Here are a few reasons:
The code is much more difficult for you to debug and maintain and is a
lot harder for other people to understand. It only takes a few
microseconds for the processor to execute code, but it might take
hours for you to figure out why it isn't working right and fix it! Your
time is valuable, right? But the computer's time is very cheap,
measured in the cost of the electricity you feed it. Usually, it is much
better to write code the most obvious way.
The code is less portable. If you use digitalRead() and digitalWrite(), it
is much easier to write code that will run on all of the Atmel
microcontrollers, whereas the control and port registers can be
different on each kind of microcontroller.
It is a lot easier to cause unintentional malfunctions with direct port
access. Notice how the line
DDRD = B11111110;
above mentions that it must leave pin 0 as an input pin. Pin 0 is the
receive line on the serial port. It would be very easy to accidentally
cause your serial port to stop working by changing pin 0 into an output
pin! Now that would be very confusing when you suddenly are unable
to receive serial data, wouldn't it?
So you might be saying to yourself, great, why would I ever want to use this
stuff then? Here are some of the positive aspects of direct port access:
If you are running low on program memory, you can use these tricks to
make your code smaller. It requires a lot fewer bytes of compiled code
to simultaneously write a bunch of hardware pins simultaneously via
the port registers than it would using a
for
loop to set each pin separately. In some cases, this might make the
difference between your program fitting in flash memory or not!
Sometimes you might need to set multiple output pins at exactly the
same time. Calling
digitalWrite(10,HIGH);
followed by
digitalWrite(11,HIGH);
PORTB |= B1100;
You may need to be able to turn pins on and off very quickly, meaning
within fractions of a microsecond. If you look at the source code in
lib/targets/arduino/wiring.c
, you will see that digitalRead() and digitalWrite() are each about a
dozen or so lines of code, which get compiled into quite a few machine
instructions. Each machine instruction requires one clock cycle at
16MHz, which can add up in time-sensitive applications. Direct port
access can do the same job in a lot fewer clock cycles.
Copy
This is an actual code sample from the Arduino 0007 runtime library, in the
file
lib\targets\arduino\winterrupts.c
. First of all, we need to know what GICR and INT0 mean. It turns out that
GICR is a control register that defines whether certain CPU interrupts are
enabled (1) or disabled (0). If we search through the Arduino standard
header files for INT0, we find various definitions. Depending on what kind of
microcontroller you are writing for, you have either
Copy
1#define INT0 6
or
Copy
1#define INT0 0
Copy
Copy
Let us study the latter case, as it is more illustrative. First of all, the value
(1 << 6)
means that we shift 1 left by 6 bits, which is the same as 26, or 64. More
useful in this context is to see this value in binary: 01000000. Then, the
bitwise NOT operator
~
is applied to this value, resulting in all the bits being toggled:
10111111. Then the bitwise AND assignment operator is used, so the code
above has the same effect as:
Copy
This has the effect of leaving all the bits alone in GICR, except for the
second-to-highest bit, which is turned off.
In the case where INT0 has been defined to 0 for your particular
microcontroller, the line of code would instead be interpreted as:
Copy
which turns off the lowest bit in the GICR register but leaves the other bits
as they were. This is an example of how the Arduino environment can
support a wide variety of microcontrollers with a single line of runtime
library source code.
There are many situations where you have a lot of data values, each of
which can be either true or false. An example of this is if you are building
your own LED grid and you want to display symbols on the grid by turning
individual LEDs on or off. An example of a 5x7 bitmap for the letter X might
look like this:
A simple way to store such an image is using an array of integers. The code
for this approach might look like this:
Copy
2 {1,1,0,0,0,1,1},
3 {0,0,1,0,1,0,0},
4 {0,0,0,1,0,0,0},
5 {0,0,1,0,1,0,0},
6 {1,1,0,0,0,1,1}
7 };
Copy
1void DisplayBitMap()
2 {
6 if (data) {
10 }
11 }
12 }
13 }
If this were the only bitmap you had in your program, this would be a
simple and effective solution to the problem. We are using 1 byte of
program memory (of which there are about 7K available in the Atmega8)
for each pixel in our bitmap, for a total of 35 bytes. This is not so bad, but
what if you wanted a bitmap for each of the 96 printable characters in the
ASCII character set? This would consume 96*35 = 3360 bytes, which would
leave a lot less flash memory for holding your program code.
There is a much more efficient way to store a bitmap. Let us replace the 2-
dimensional array above with a 1-dimensional array of bytes. Each byte
contains 8 bits, and we will use the lowest 7 bits of each to represent the 7
pixels in a column of our 5x7 bitmap:
Copy
2 B1100011,
3 B0010100,
4 B0001000,
5 B0010100,
6 B1100011
7 };
(Here we are using the predefined binary constants available starting in
Arduino 0007.) This allows us to use 5 bytes for each bitmap instead of
35. But how do we make use of this more compact data format? Here is the
answer: we rewrite the function DisplayBitMap() to access the individual
bits in each byte of the BitMap...
Copy
1void DisplayBitMap()
2 {
8 } else {
10 }
11 }
12 }
13 }
Copy
The expression
(1<<y)
selects a given bit inside
data
that we want to access. Then using bitwise AND,
data & (1<<y)
tests the given bit. If that bit is set, a nonzero value results, causing the
if
to see it as being true. Otherwise, if the bit is zero, it is treated as false, so
the
else
executes.
Quick Reference
In this quick reference, we refer to the bits in a 16-bit integer starting with
the least significant bit as bit 0, and the most significant bit (the sign bit if
the integer is signed) as bit 15, as illustrated in this diagram:
n
, its value is assumed to be 0 through 15.
Copy
Copy
1x &= ~(1 << n); // forces nth bit of x to be 0. all other bits left alone.
Copy
1x &= (1<<(n+1))-1; // leaves alone the lowest n bits of x; all higher bits
set to 0.
Copy
1x |= (1 << n); // forces nth bit of x to be 1. all other bits left alone.
Copy
1x ^= (1 << n); // toggles nth bit of x. all other bits left alone.
Copy
&
and boolean
&&
. It returns true if and only if the given 32-bit integer
x
is a perfect power of 2, i.e., 1, 2, 4, 8, 16, 32, 64, etc. For example, calling
IsPowerOfTwo(64)
will return
true
, but
IsPowerOfTwo(65)
returns
false
. To see how this function works, let us use the number 64 as an example of
a power of 2. In binary, 64 is
1000000
. When we subtract 1 from
1000000
, we get
0111111
. Applying bitwise
&
, the result is
0000000
. But if we do the same with 65 (binary 1000001), we get
1000001 & 1000000 == 1000000
, which is not zero.
Copy
2 {
4 }
Here is a function that counts how many bits in the 16-bit integer
x
are 1 and returns the count:
Copy
2 {
3 int count = 0;
5 if (x & (1<<n)) {
6 ++count;
7 }
8 }
9 return count;
10 }
Copy
2 {
5 x &= x - 1;
6 return count;
7 }