- •Acknowledgments
- •Preface
- •Who Should Read This Book
- •What’s in This Book
- •Arduino Uno and the Arduino Platform
- •Code Examples and Conventions
- •Online Resources
- •Complete Parts List
- •The Parts You Need
- •Starter Packs
- •1. Welcome to the Arduino
- •What You Need
- •What Exactly Is an Arduino?
- •Exploring the Arduino Board
- •Installing the Arduino IDE
- •Meeting the Arduino IDE
- •Hello, World!
- •Compiling and Uploading Programs
- •What If It Doesn’t Work?
- •Exercises
- •2. Creating Bigger Projects with the Arduino
- •What You Need
- •Managing Projects and Sketches
- •Changing Preferences
- •Using Serial Ports
- •What If It Doesn’t Work?
- •Exercises
- •3. Building Binary Dice
- •What You Need
- •Working with Breadboards
- •Using an LED on a Breadboard
- •First Version of a Binary Die
- •Working with Buttons
- •Adding Your Own Button
- •Building a Dice Game
- •What If It Doesn’t Work?
- •Exercises
- •4. Building a Morse Code Generator Library
- •What You Need
- •Learning the Basics of Morse Code
- •Building a Morse Code Generator
- •Fleshing Out the Morse Code Generator’s Interface
- •Outputting Morse Code Symbols
- •Installing and Using the Telegraph Class
- •Publishing Your Own Library
- •What If It Doesn’t Work?
- •Exercises
- •5. Sensing the World Around Us
- •What You Need
- •Measuring Distances with an Ultrasonic Sensor
- •Increasing Precision Using Floating-Point Numbers
- •Increasing Precision Using a Temperature Sensor
- •Creating Your Own Dashboard
- •What If It Doesn’t Work?
- •Exercises
- •What You Need
- •Wiring Up the Accelerometer
- •Bringing Your Accelerometer to Life
- •Finding and Polishing Edge Values
- •Building Your Own Game Controller
- •More Projects
- •What If It Doesn’t Work?
- •Exercises
- •7. Writing a Game for the Motion-Sensing Game Controller
- •Writing a GameController Class
- •Creating the Game
- •What If It Doesn’t Work?
- •Exercises
- •8. Generating Video Signals with an Arduino
- •What You Need
- •How Analog Video Works
- •Building a Digital-to-Analog Converter (DAC)
- •Connecting the Arduino to Your TV Set
- •Using the TVout Library
- •Building a TV Thermometer
- •Working with Graphics in TVout
- •What If It Doesn’t Work?
- •Exercises
- •9. Tinkering with the Wii Nunchuk
- •What You Need
- •Wiring a Wii Nunchuk
- •Talking to a Nunchuk
- •Building a Nunchuk Class
- •Using Our Nunchuk Class
- •Creating Your Own Video Game Console
- •Creating Your Own Video Game
- •What If It Doesn’t Work?
- •Exercises
- •10. Networking with Arduino
- •What You Need
- •Using Your PC to Transfer Sensor Data to the Internet
- •Registering an Application with Twitter
- •Tweeting Messages with Processing
- •Communicating Over Networks Using an Ethernet Shield
- •Using DHCP and DNS
- •What If It Doesn’t Work?
- •Exercises
- •Emailing from the Command Line
- •11. Creating a Burglar Alarm with Email Notification
- •What You Need
- •Emailing Directly from an Arduino
- •Detecting Motion Using a Passive Infrared Sensor
- •Bringing It All Together
- •What If It Doesn’t Work?
- •Exercises
- •What You Need
- •Understanding Infrared Remote Controls
- •Grabbing Remote Control Codes
- •Cloning a Remote
- •Controlling Infrared Devices Remotely with Your Browser
- •Building an Infrared Proxy
- •What If It Doesn’t Work?
- •Exercises
- •13. Controlling Motors with Arduino
- •What You Need
- •Introducing Motors
- •First Steps with a Servo Motor
- •Building a Blaminatr
- •What If It Doesn’t Work?
- •Exercises
- •Current, Voltage, and Resistance
- •Electrical Circuits
- •Learning How to Use a Wire Cutter
- •Learning How to Solder
- •Learning How to Desolder
- •The Arduino Programming Language
- •Bit Operations
- •Learning More About Serial Communication
- •Serial Communication Using Various Languages
- •What Are Google Chrome Apps?
- •Creating a Minimal Chrome App
- •Starting the Chrome App
- •Exploring the Chrome Serial API
- •Writing a SerialDevice Class
- •Index
Outputting Morse Code Symbols • 65
Arduino IDE, and you can find them in the hardware/arduino/cores/arduino directory of the IDE. Have a look at Arduino.h (in older Arduino versions this file was named WProgram.h). It contains all the constants we have used so far and many more. It also declares many useful macros and the Arduino’s most basic functions.
When you edit regular sketches, you don’t have to worry about including any standard header files, because the IDE does it automatically behind the scenes. As soon as you create more complex projects that contain “real” C++ code, you have to manage everything yourself. You have to explicitly import all the libraries you need, even for basic stuff such as the Arduino constants.
After importing all necessary header files, we define two string arrays named
LETTERS and DIGITS. They contain the Morse code for all letters and digits, and we’ll use them later to translate regular text into Morse code. Before we do that, we define the constructor that is responsible for creating and initializing new Telegraph objects:
TelegraphLibrary/telegraph.cpp
Telegraph::Telegraph(const int output_pin, const int dit_length) { _output_pin = output_pin;
_dit_length = dit_length; _dah_length = dit_length * 3; pinMode(_output_pin, OUTPUT);
}
The constructor expects two arguments: the number of the pin the Morse code should be sent to and the length of a dit measured in milliseconds. Then it stores these values in corresponding instance variables, calculates the correct length of a dah, and turns the communication pin into an output pin.
You’ve probably noticed that all private instance variables start with an underscore. I like that convention personally, but it isn’t enforced by C++ or the Arduino IDE.
Outputting Morse Code Symbols
After everything has been initialized, we can start to output Morse code symbols. We use several small helper methods to make our code as readable as possible:
TelegraphLibrary/telegraph.cpp
void Telegraph::output_code(const char* code) { const unsigned int code_length = strlen(code);
for (unsigned int i = 0; i < code_length; i++) { if (code[i] == '.')
report erratum • discuss
Chapter 4. Building a Morse Code Generator Library • 66
dit(); else
dah();
if (i != code_length - 1) delay(_dit_length);
}
}
void Telegraph::dit() { Serial.print("."); output_symbol(_dit_length);
}
void Telegraph::dah() { Serial.print("-"); output_symbol(_dah_length);
}
void Telegraph::output_symbol(const int length) { digitalWrite(_output_pin, HIGH); delay(length);
digitalWrite(_output_pin, LOW);
}
The function output_code takes a Morse code sequence consisting of dots and dashes and turns it into calls to dit and dah. The dit and dah methods then print a dot or a dash to the serial port and delegate the rest of the work to output_symbol, passing it the length of the Morse code symbol to be emitted. output_symbol sets the output pin to HIGH for the length of the symbol, and then it sets it back to LOW. Everything works exactly as described in the Morse code timing scheme, and only the implementation of send_message is missing:
TelegraphLibrary/telegraph.cpp
Line 1 void Telegraph::send_message(const char* message) {
-for (unsigned int i = 0; i < strlen(message); i++) {
-const char current_char = toupper(message[i]);
-if (isalpha(current_char)) {
5output_code(LETTERS[current_char - 'A']);
-delay(_dah_length);
-} else if (isdigit(current_char)) {
-output_code(DIGITS[current_char - '0']);
-delay(_dah_length);
10 } else if (current_char == ' ') {
-Serial.print(" ");
-delay(_dit_length * 7);
-}
-}
15 |
Serial.println(); |
- |
} |
report erratum • discuss
Installing and Using the Telegraph Class • 67
send_message outputs a message character by character in a loop. In line 3, we turn the current character into uppercase, because lowercase characters are not defined in Morse code (that’s why you can’t implement a chat client using Morse code). Then we check whether the current character is a letter using C’s isalpha function. If it is, we use the character to determine its Morse code representation that is stored in the LETTERS array. To do that, we use an old trick: in the ASCII table, all letters (and digits) appear in the correct order—that is, A=65, B=66, and so on. To transform the current character into an index for the LETTERS array, we have to subtract 65 (or 'A') from its ASCII code. When we have determined the correct Morse code, we pass it to output_symbol and delay the program for the length of a dah afterward.
The algorithm works exactly the same for outputting digits; we only have to index the DIGITS array instead of the LETTERS array, and we have to subtract the ASCII value of the character '0'.
In line 10, we check whether we received a blank character. If yes, we print a blank character to the serial port and wait for seven dits. All other characters are ignored: we only process letters, digits, and blanks. At the end of the method, we send a newline character to the serial port to mark the end of the message.
Installing and Using the Telegraph Class
Our Telegraph class is complete, and we should now create some example sketches that actually use it. This is important for two reasons: we can test our library code, and for users of our class it’s good documentation for how to use it.
The Arduino IDE looks for libraries in two places: in its global libraries folder relative to its installation directory and in the user’s local sketchbook directory. During development, it’s best to use the local sketchbook directory. You can find its location in the IDE’s Preferences (see Figure 14, Find the sketchbook location in the Preferences, on page 68). Create a new directory named libraries in the sketchbook directory.
To make the Telegraph class available, create a Telegraph subfolder in the libraries folder. Then copy telegraph.h and telegraph.cpp to the new libraries/Telegraph folder. (Do not copy TelegraphLibrary.ino.) Restart the IDE.
Let’s start with the mother of all programs: “Hello, world!” Create a new sketch named HelloWorld and enter the following code:
report erratum • discuss
Chapter 4. Building a Morse Code Generator Library • 68
Figure 14—Find the sketchbook location in the Preferences.
TelegraphLibrary/examples/HelloWorld/HelloWorld.ino
#include "telegraph.h"
const unsigned int BAUD_RATE = 9600; const unsigned int OUTPUT_PIN = 13; const unsigned int DIT_LENGTH = 200;
Telegraph telegraph(OUTPUT_PIN, DIT_LENGTH);
void setup() { Serial.begin(BAUD_RATE);
}
void loop() { telegraph.send_message("Hello, world!"); delay(5000);
}
This sketch emits the string “Hello, world!” as Morse code every five seconds. To achieve this, we include the definition of our Telegraph class, and we define constants for the pin our LED is connected to and for the length of our dits. Then we create a global Telegraph object and an empty setup function. In loop, we then invoke send_message on our Telegraph instance every five seconds.
When you compile this sketch, the Arduino IDE automatically compiles the telegraph library, too. If you forgot to copy the library files to the libraries/Telegraph folder, you’ll get an error message such as “Telegraph does not name a type.”
report erratum • discuss
Installing and Using the Telegraph Class • 69
If you’ve copied the files but made any syntactical errors, you’ll also be notified now. If you have to correct some errors, make sure you change your original source code files. After you’ve fixed the errors, copy the files to the libraries folder again, and don’t forget to restart the IDE.
Turning a static string into Morse code is nice, but wouldn’t it be great if our program could work for arbitrary strings? So, let’s add a more sophisticated example. This time, we’ll write code that reads messages from the serial port and feeds them into a Telegraph instance.
Create a new sketch named MorseCodeGenerator and enter the following code:
TelegraphLibrary/examples/MorseCodeGenerator/MorseCodeGenerator.ino
#include "telegraph.h"
const unsigned int OUTPUT_PIN = 13; const unsigned int DIT_LENGTH = 200; const unsigned int MAX_MESSAGE_LEN = 128; const unsigned int BAUD_RATE = 9600; const char NEWLINE = '\n';
char message_text[MAX_MESSAGE_LEN]; int index = 0;
Telegraph telegraph(OUTPUT_PIN, DIT_LENGTH);
void setup() { Serial.begin(BAUD_RATE);
}
void loop() {
if (Serial.available() > 0) {
int current_char = Serial.read();
if (current_char == NEWLINE || index == MAX_MESSAGE_LEN - 1) { message_text[index] = 0;
index = 0; telegraph.send_message(message_text);
}else {
message_text[index++] = current_char;
}
}
}
Again, we include the header file of the Telegraph class, and as usual we define some constants: OUTPUT_PIN defines the pin our LED is connected to, and
DIT_LENGTH contains the length of a dit measured in milliseconds. NEWLINE is set to the ASCII code of the newline character. We need it to determine the
report erratum • discuss
Chapter 4. Building a Morse Code Generator Library • 70
end of the message to be emitted as Morse code. Finally, we set MAX_MESSAGE_LEN to the maximum length of the messages we are able to send.
Next we define three global variables: message_text is a character buffer that gets filled with the data we receive on the serial port. index keeps track of our current position in the buffer, and telegraph is the Telegraph object we’ll use to convert a message into “blinkenlights.”2
setup initializes the serial port, and in loop we check whether new data has arrived, calling Serial.available. We read the next byte if new data is available, and we check whether it is a newline character or whether it is the last byte that fits into our character buffer. In both cases, we set the last byte of message_text to 0, because strings in C/C++ are null-terminated. We also reset index so we can read the next message, and finally we send the message using our telegraph. In all other cases, we add the latest byte to the current message text and move on.
You should compile and upload the program now. Open the serial monitor and choose “Newline” from the line endings drop-down menu at the bottom of the window. With this option set, the serial monitor will automatically append a newline character to every line it sends to the Arduino. Enter a message such as your name, click the Send button, and see how the Arduino turns it into light. In the following figure, you can see what happens when you enter my name.
2.http://en.wikipedia.org/wiki/Blinkenlights
report erratum • discuss
