Tải bản đầy đủ (.pdf) (5 trang)

Apress - Smart Home Automation with Linux (2010)- P18 ppsx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (279.7 KB, 5 trang )

CHAPTER 2 ■ APPLIANCE HACKING

68

In addition to light, you can also measure temperature (thermistors), distances (ultrasonic range
finders), and rotary positions (by attaching a handle or wheel to the spindle of a potentiometer).
Sending Digital Outputs
This is as simple as it sounds and includes those cases where you want to send nothing more than a
simple on/off to something like a light switch or small motor. The code requires a simple setup and
invocation like this:

int outputLightPin = 2;
pinMode(outputLightPin, OUTPUT);
//
digitalWrite(outputLightPin, bState ? TRUE : FALSE);

From here, it’s all about the circuit.
Each pin on the Arduino is able to source current, up to around 40 milliamps. This is enough for
most small loads such as lights, buffers, and some small motors. If your device uses no more than 300
milliamps, then you can draw this from the circuit board itself using the Arduino as a switch only with a
circuit like that in Figure 2-5.


Figure 2-5. A transistor switch circuit, allowing you to draw up to 300mA
For anything larger, you will need to employ a relay and separate power source, as shown in
Figure 2-6.

CHAPTER 2 ■ APPLIANCE HACKING

69



Figure 2-6. Using a relay to control high power loads
■ Note In reality, the Arduino is good for higher power loads up to 800mA. But for dirty loads, such as motors, the
300mA is probably more conservatively sensible.
Sending Analog Outputs
As mentioned previously, analog output is available on the basic Arduino only when using PWM. This is
supported only on pins 3, 5, 6, 9, 10, 11, and 21.
10
The pulsing of the output pin to provide the output is
handled automatically, including the setup, so you need only to write this:

analogWrite(analogWritePin, value); // value is between 0 and 255, inclusive

This will allow you to vary the brightness of LEDs and the volume of piezo-buzzers and speakers,
but not a lot else. In reality, you won’t need a lot else in home automation environs. Moving a motor to a
specific position, for example, is better done with servo or stepper motors, and many other forms of
positioning should be done through the use of feedback loops—switching the motor on to begin
movement and switching it off when a sensor reveals it has gone far enough.


10
Older boards using the ATmega8 support only pins 9,10, and 11, while the newer Arduino Mega can support PWM
on 12 of its pins.
CHAPTER 2 ■ APPLIANCE HACKING

70

Creating Audio Outputs
This is one of the simplest forms of human-friendly feedback the Arduino can provide, because the
circuit needs only a buzzer attached to a digital output pin. The code is a simple loop changing the

output state between on and off 440 times a second, for example, to produce the A note above middle C.
The examples on the main Arduino site provide the necessary code to make it beep and play short
tunes. For those looking for more advanced music control, there is Armstrong
(www.bluedust.dontexist.com/armstrong),

the Arduino music system, which provides a small melody
processor allowing you to play the chimes of Big Ben with code like this:

ancInitialize(OUTPUT_LOCAL);
ancAssignChannelToPin(CHANNEL_OUTPUT_PIEZO_SPEAKER, piezoPin);

char *pChimesPhrase1 = "L32O4edcL64O3g";
char *pChimesPhrase2 = "L32O4cedL64O3g";
char *pChimesPhrase3 = "L32O4cdeL64c";
char *pChimesPhrase4 = "L32O4ecdL64O3g";
char *pChimesPhrase5 = "L32O3gO4deL64c";

// a quarter past
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase1);

// half past
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase2);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase3);

// a quarter to

ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase4);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase5);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase1);


// top of the hour
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase2);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase3);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase4);
ampPlayString(CHANNEL_OUTPUT_PIEZO_SPEAKER, pChimesPhrase5);

Using the various shields provides more complex audio output, including sample playback.
Communication with a PC
The basic Arduino allows bidirectional communication with a PC through its built-in USB port. This uses
the same serial port that’s used to upload the program in the first place. It must be set up first before
data can be sent or received, both of which are supported with this method:

Serial.begin(9600);

The Arduino can read data from the PC only on a byte-by-byte basis, so you will need to read it
within a loop using code like this:
CHAPTER 2 ■ APPLIANCE HACKING

71

int incomingData = Serial.read();

Note, however, that this function is blocking. That is, it will not return from the read function until
there is data on the serial port. If your device responds only to messages, then this will work fine.
However, it is more usual to place this at the start of your loop, surrounded with this:

if (Serial.available() > 0) { /* */ }

Writing data from the Arduino back to the PC, however, is easier since the size of the data is already
known. This can be handled by the Serial.print or Serial.println function for quick and easy string

messages. Or individual bytes can be written using Serial.write:

Serial.write(byteData);

This is useful for applications wanting to transfer a lot of data. But for testing and development, I
find a simple ASCII-based protocol easier to work with, because a simple serial terminal allows me to
send and receive messages in human-readable text. The Minerva feature, MINX (Minerva INput
transfer), uses the delimiters <| and |> to surround control messages, allowing an Arduino to pass
messages back to the PC so that further processing can take place, without affecting any other debugging
or trace messages. I’ll cover this fully in Chapter 7.
■ Note Some models of Arduino, such as the Mega, have three additional serial ports addressable as Serial1,
Serial2, and Serial3.
On the PC side of this transmit-receive equation, you have a much simpler job since everything in
Linux is treated like a file. You can therefore issue this:

tail -f /dev/ttyUSB0

To see all the data that is sent back from the Arduino and introduce commands to the board,
use this:

echo -n send data > /dev/ttyUSB0

It is from this that demonstrates the benefit of an ASCII-based protocol. In the simplest case, you
can issue this:

Serial.print("1");

from the Arduino to switch the PC control program into an on state, with an equivalent for off. This
makes the C program very simple:


CHAPTER 2 ■ APPLIANCE HACKING

72

// USB script trigger
#include <stdio.h>

char *szUSBDevice = "/dev/ttyUSB0";
int main() {
char v;

FILE *fp = fopen(szUSBDevice, "r");
if (!fp) {
printf("Failed to open USB ");
return 1;
}


while(1) {
if (fread(&v, 1, 1, fp)) {
if (v == '1') {
// button pressed
} else if (v == '0') {
// button released
} else {
printf("%c", v);
fflush(stdout);
}
}
}


return 0;
}

This also includes the functionality to write noncontrol codes to stdout, which may be redirected to
a log file. If you compile the previous program with g++ as arduino_read, you can start it as a process in
the background, making it daemon-like for very little effort:

./arduino_read > logfile 2>&1 &
Arduino Hardware
For some complex applications, the ATmega168 chip on the Arduino board is not powerful enough to
handle the task. So, in common with other computers, additional chips are necessary to ease the
burden. In keeping with the modular design of the Arduino, these chips are built up into stand-alone
boards with the necessary interfacing circuitry so that they can be directly mounted on top of the
existing Arduino board. For this reason, they are known as shields. Most shields also include a pass-
through so that other shields can be placed on top of it. There is then a separate software library that is
used to control the device and that is copied into the Arduino/hardware/libraries directory.
■ Note Not all shields are compatible with all models of Arduino.

×