Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon

How-To Tutorials - Single Board Computers

71 Articles
article-image-working-cloud
Packt
02 May 2016
33 min read
Save for later

Working with the Cloud

Packt
02 May 2016
33 min read
In this article by Gastón C. Hillar , author of book Internet of Things with Python, we will take advantage of many cloud services to publish and visualize data collected for sensors and to establish bi-directional communications between Internet-connected things. (For more resources related to this topic, see here.) Sending and receiving data in real-time through Internet with PubNub We want to send and receive data in real-time through the Internet and a RESTful API is not the most appropriate option to do this. Instead, we will work with a publish/subscribe model-based on a protocol that is lighter than the HTTP protocol. Specifically, we will use a service-based on the MQ Telemetry Transport (MQTT) protocol. The MQTT protocol is a machine-to-machine (M2M) connectivity protocol. MQTT is a lightweight messaging protocol that runs on top of the TCP/IP protocol and works with a publish-subscribe mechanism. It is possible for any device to subscribe to a specific channel (also known as topic) and receive all the messages published to this channel. In addition, the device can publish message to this or other channel. The protocol is becoming very popular in IoT and M2M projects. You can read more about the MQTT protocol in the following Webpage: http://mqtt.org. PubNub provides many cloud-based services and one of them allows us to easily stream data and signal any device in real-time, working with the MQTT protocol under the hoods. We will take advantage of this PubNub service to send and receive data in real-time through Internet and make it easy to control our Intel Galileo Gen 2 board through the Internet. As PubNub provides a Python API with high quality documentation and examples, it is extremely easy to use the service in Python. PubNub defines itself as the global data stream network for IoT, Mobile and Web applications. You can read more about PubNub in its Webpage: http://www.pubnub.com. In our example, we will take advantage of the free services offered by PubNub and we won't use some advanced features and additional services that might empower our IoT project connectivity requirements but also require a paid subscription. PubNub requires us to sign up and create an account with a valid e-mail and a password before we can create an application within PubNub that allows us to start using their free services. We aren't required to enter any credit card or payment information. If you already have an account at PubNub, you can skip the next step. Once you created your account PubNub will redirect you to the admin portal that lists your PubNub applications. It is necessary to generate your PubNub publish and subscribe keys in order to send and receive messages in the network. A new pane will represent the application in the admin portal. The following screenshot shows the Temperature Control application pane in the PubNub admin portal. Click on the Temperature Control pane and PubNub will display the Demo Keyset pane that has been automatically generated for the application. Click on this pane and PubNub will display the publish, subscribe and secret keys. We must copy and paste each of the keys to use them in our code that will publish messages and subscribe to them. The following screenshot shows the prefixes for the keys and the remaining characters have been erased in the image. In order to copy the secret key, you must click on the eye icon at the right-hand side of the key and PubNub will make all the characters visible. Now, we will use pip installer to install PubNub Python SDK 3.7.6. We just need to run the following command in the SSH terminal to install the package. Notice that it can take a few minutes to complete the installation. pip install pubnub The last lines for the output will indicate that the pubnub package has been successfully installed. Don't worry about the error messages related to building wheel and the insecure platform warning. Downloading pubnub-3.7.6.tar.gz Collecting pycrypto>=2.6.1 (from pubnub) Downloading pycrypto-2.6.1.tar.gz (446kB) 100% |################################| 446kB 25kB/s Requirement already satisfied (use --upgrade to upgrade): requests>=2.4.0 in /usr/lib/python2.7/site-packages (from pubnub) Installing collected packages: pycrypto, pubnub Running setup.py install for pycrypto Installing collected packages: pycrypto, pubnub Running setup.py install for pycrypto Running setup.py install for pubnub Successfully installed pubnub-3.7.6 pycrypto-2.6.1 We will use iot_python_chapter_08_03.py (you will find this in the code bundle) code as a baseline to add new features that will allow us to perform the following actions with PubNub messages sent to a specific channel from any device that has a Web browser: Rotate the servo's shaft to display a temperature value in degrees Fahrenheit received as part of the message Display a line of text received as part of the message at the bottom of the OLED matrix We will use the recently installed pubnub module to subscribe to a specific channel and run code when we receive messages in the channel. We will create a MessageChannel class to represent the communications channel, configure the PubNub subscription and declare the code for the callbacks that are going to be executed when certain events are fired. The code file for the sample is iot_python_chapter_09_02.py (you will find this in the code bundle). Remember that we use the code file iot_python_chapter_08_03.py (you will find this in the code bundle)as a baseline, and therefore, we will add the class to the existing code in this file and we will create a new Python file. Don't forget to replace the strings assigned to the publish_key and subscribe_key local variables in the __init__ method with the values you have retrieved from the previously explained PubNub key generation process. import time from pubnub import Pubnub class MessageChannel: command_key = "command" def __init__(self, channel, temperature_servo, oled): self.temperature_servo = temperature_servo self.oled = oled self.channel = channel # Publish key is the one that usually starts with the "pub-c-" prefix # Do not forget to replace the string with your publish key publish_key = "pub-c-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Subscribe key is the one that usually starts with the "sub-c" prefix # Do not forget to replace the string with your subscribe key subscribe_key = "sub-c-xxxxxxxx-xxxx-xxxx-xxxx- xxxxxxxxxxxx" self.pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key) self.pubnub.subscribe(channels=self.channel, callback=self.callback, error=self.callback, connect=self.connect, reconnect=self.reconnect, disconnect=self.disconnect) def callback(self, message, channel): if channel == self.channel: if self.__class__.command_key in message: if message[self.__class__.command_key] == "print_temperature_fahrenheit": self.temperature_servo.print_temperature (message["temperature_fahrenheit"]) elif message[self.__class__.command_key] == "print_information_message": self.oled.print_line(11, message["text"]) print("I've received the following message: {0}".format(message)) def error(self, message): print("Error: " + str(message)) def connect(self, message): print("Connected to the {0} channel". format(self.channel)) print(self.pubnub.publish( channel=self.channel, message="Listening to messages in the Intel Galileo Gen 2 board")) def reconnect(self, message): print("Reconnected to the {0} channel". format(self.channel)) def disconnect(self, message): print("Disconnected from the {0} channel". Format(self.channel)) The MessageChannel class declares the command_key class attribute that defines the key string that defines what the code will understand as the command. Whenever we receive a message that includes the specified key string, we know that the value associated to this key in the dictionary will indicate the command that the message wants the code running in the board to be processed. Each command requires additional key-value pairs that provide the necessary information to execute the command. We have to specify the PubNub channel name, the TemperatureServo instance and the Oled instance in the channel, temperature_servo and oled required arguments. The constructor, that is, the __init__ method, saves the received arguments in three attributes with the same names. The channel argument specifies the PubNub channel to which we are going to subscribe to listen to the messages that other devices send to this channel. We will also publish messages to this channel, and therefore, we will be both a subscriber and a publisher for this channel. In this case, we will only subscribe to one channel. However, it is very important to know that we are not limited to subscribe to a single channel, we might subscribe to many channels. Then, the constructor declares two local variables: publish_key and subscribe_key. These local variables save the publish and subscribe keys we had generated with the PubNub admin portal. Then, the code creates a new Pubnub instance with publish_key and subscribe_key as the arguments, and saves the reference for the new instance in the pubnub attribute. Finally, the code calls the subscribe method for the new instance to subscribe to data on the channel saved in the channel attribute. Under the hoods, the subscribe method makes the client create an open TCP socket to the PubNub network that includes an MQTT broker and starts listening to messages on the specified channel. The call to this method specifies many methods declared in the MessageChannel class for the following named arguments: callback: Specifies the function that will be called when there is a new message received from the channel error: Specifies the function that will be called on an error event connect: Specifies the function that will be called when a successful connection is established with the PubNub cloud reconnect: Specifies the function that will be called when a successful re-connection is completed with the PubNub cloud disconnect: Specifies the function that will be called when the client disconnects from the PubNub cloud This way, whenever one of the previously enumerated events occur, the specified method will be executed. The callback method receives two arguments: message and channel. First, the method checks whether the received channel matches the value in the channel attribute. In this case, whenever the callback method is executed, the value in the channel argument will always match the value in the channel attribute because we just subscribed to one channel. However, in case we subscribe to more than one channel, is is always necessary to check the channel in which the message was sent and in which we are receiving the message. Then, the code checks whether the command_key class attribute is included in the message dictionary. If the expression evaluates to True, it means that the message includes a command that we have to process. However, before we can process the command, we have to check which is the command, and therefore, it is necessary to retrieve the value associated with the key equivalent to the command_key class attribute. The code is capable of running code when the value is any of the following two commands: print_temperature_fahrenheit: The command must specify the temperature value expressed in degrees Fahrenheit in the value of the temperature_fahrenheit key. The code calls the self.temperature_servo.print_temperature method with the temperature value retrieved from the dictionary as an argument. This way, the code moves the servo's shaft-based on the specified temperature value in the message that includes the command. print_information_message: The command must specify the line of text that has to be displayed at the bottom of the OLED matrix in the value of the print_information_message key. The code calls the self.oled.print_line method with 11 and the text value retrieved from the dictionary as arguments. This way, the code displays the text received in the message that includes the command at the bottom of the OLED matrix. No matter whether the message included a valid command or not, the method prints the raw message that it received in the console output. The connect method prints a message indicating that a connection has been established with the channel. Then, the method prints the results of calling the self.pubnub.publish method that publishes a message in the channel name saved in self.channel with the following message: "Listening to messages in the Intel Galileo Gen 2 board". In this case, the call to this method runs with a synchronous execution. We will work with asynchronous execution for this method in our next example. Currently, we are already subscribed to this channel, and therefore, we will receive the previously published message and the callback method will be executed with this message as an argument. However, as the message doesn't include the key that identifies a command, the code in the callback method will just display the received message and it won't process any of the previously analyzed commands. The other methods declared in the MessageChannel class just display information to the console output about the event that has occurred. Now, we will use the previously coded MessageChannel class to create a new version of the __main__ method that uses the PubNub cloud to receive and process commands. The new version doesn't rotate the servo's shaft when the ambient temperature changes, instead, it will do this when it receives the appropriate command from any device connected to PubNub cloud. The following lines show the new version of the __main__ method. The code file for the sample is iot_python_chapter_09_02.py (you will find this in the code bundle). if __name__ == "__main__": temperature_and_humidity_sensor = TemperatureAndHumiditySensor(0) oled = TemperatureAndHumidityOled(0) temperature_servo = TemperatureServo(3) message_channel = MessageChannel("temperature", temperature_servo, oled) while True: temperature_and_humidity_sensor. measure_temperature_and_humidity() oled.print_temperature( temperature_and_humidity_sensor .temperature_fahrenheit, temperature_and_humidity_sensor.temperature_celsius) oled.print_humidity( temperature_and_humidity_sensor.humidity) print("Ambient temperature in degrees Celsius: {0}". format(temperature_and_humidity_sensor .temperature_celsius)) print("Ambient temperature in degrees Fahrenheit: {0}". format(temperature_and_humidity_sensor .temperature_fahrenheit)) print("Ambient humidity: {0}". format(temperature_and_humidity_sensor.humidity)) # Sleep 10 seconds (10000 milliseconds) time.sleep(10) The highlighted line creates an instance of the previously coded MessageChannel class with "temperature", temperature_servo and oled as the arguments. The constructor will subscribe to the temperature channel in the PubNub cloud, and therefore, we must send the messages to this channel in order to send the commands that the code will process with an asynchronous execution. The loop will read the values from the sensor and print the values to the console similar to the previous version of the code, and therefore, we will have code running in the loop and listening to the messages in the temperature channel in the PubNub cloud. We will start the example later because we want to subscribe to the channel in the PubNub debug console before we run the code in the board. Publishing messages with commands through the PubNub cloud Now, we will take advantage of the PubNub console to send messages with commands to the temperature channel and make the Python code running on the board process these commands. In case you have logged out of PubNub, login again and click on the Temperature Control pane in the Admin Portal. PubNub will display the Demo Keyset pane. Click on the Demo Keyset pane and PubNub will display the publish, subscribe and secret keys. This way, we select the keyset that we want to use for our PubNub application. Click on Debug Console on the sidebar located the left-hand side of the screen. PubNub will create a client for a default channel and subscribe to this channel using the secret keys we have selected in the previous step. We want to subscribe to the temperature channel, and therefore, enter temperature in the Default Channel textbox within a pane that includes the Add client button at the bottom. Then, click on Add client and PubNub will add a new pane with a random client name as a title and the channel name, temperature, in the second line. PubNub makes the client subscribe to this channel and we will be able to receive messages published to this channel and send messages to this channel. The following picture shows the pane for the generated client named Client-ot7pi, subscribed to the temperature channel. Notice that the client name will be different when you follow the explained steps. The client pane displays the output generated when PubNub subscribed the client to the channel. PubNub returns a formatted response for each command. In this case, it indicates that the status is equal to Subscribed and the channel name is temperature. [1,"Subscribed","temperature"] Now, it is time to start running the example in the Intel Galileo Gen 2 board. The following line will start the example in the SSH console. python iot_python_chapter_09_02.py After you run the example, go to the Web browser in which you are working with the PubNub debug console. You will see the following message listed in the previously created client: "Listening to messages in the Intel Galileo Gen 2 board" The Python code running in the board published this message, specifically, the connect method in the MessageChannel class sent this message after the application established a connection with the PubNub cloud. The following picture shows the message listed in the previously created client. Notice that the icon at the left-hand side of the text indicates it is a message. The other message was a debug message with the results of subscribing to the channel. At the bottom of the client pane, you will see the following text and the SEND button at the right-hand side: {"text":"Enter Message Here"} Now, we will replace the previously shown text with a message. Enter the following JSON code and click SEND: {"command":"print_temperature_fahrenheit", "temperature_fahrenheit": 50 } The text editor where you enter the message has some issues in certain browsers. Thus, it is convenient to use your favorite text editor to enter the JSON code, copy it and then past it to replace the text that is included by default in the text for the message to be sent. After you click SEND, the following lines will appear in the client log. The first line is a debug message with the results of publishing the message and indicates that the message has been sent. The formatted response includes a number (1 message), the status (Sent) and a time token. The second line is the message that arrives to the channel because we are subscribed to the temperature channel, that is, we also receive the message we sent. [1,"Sent","14594756860875537"] { "command": "print_temperature_fahrenheit", "temperature_fahrenheit": 50 } The following picture shows the messages and debug messages log for the PubNub client after we clicked the SEND button. After you publish the previous message, you will see the following output in the SSH console for the Intel Galileo Gen 2 board. You will notice the servo's shaft rotates to 50 degrees. I've received the following message: {u'command': u'print_temperature_fahrenheit', u'temperature_fahrenheit': 50} Now, enter the following JSON code and click SEND: {"command":"print_information_message", "text": "Client ready"} After you click SEND, the following lines will appear in the client log. The first line is a debug message with the previously explained formatted response with the results of publishing the message and indicates that the message has been sent. The second line is the message that arrives to the channel because we are subscribed to the temperature channel, that is, we also receive the message we sent. [1,"Sent","14594794434885921"] { "command": "print_information_message", "text": "Client ready" } The following picture shows the messages and debug messages log for the PubNub client after we clicked the SEND button. After you publish the previous message, you will see the following output in the SSH console for the Intel Galileo Gen 2 board. You will see the following text displayed at the bottom of the OLED matrix: Client ready. I've received the following message: {u'text': u'Client ready', u'command': u'print_information_message'} When we published the two messages with the commands, we have definitely noticed a problem. We don't know whether the command was processed or not in the code that is running on the IoT device, that is, in the Intel Galileo Gen 2 board. We know that the board started listening messages in the temperature channel, but we don't receive any kind of response from the IoT device after the command has been processed. Working with bi-directional communications We can easily add a few lines of code to publish a message to the same channel in which we are receiving messages to indicate that the command has been successfully processed. We will use our previous example as a baseline and we will create a new version of the MessageChannel class. The code file was iot_python_chapter_09_02.py (you will find this in the code bundle). Don't forget to replace the strings assigned to the publish_key and subscribe_key local variables in the __init__ method with the values you have retrieved from the previously explained PubNub key generation process. The following lines show the new version of the MessageChannel class that publishes a message after a command has been successfully processed. The code file for the sample is iot_python_chapter_09_03.py (you will find this in the code bundle). import time from pubnub import Pubnub class MessageChannel: command_key = "command" successfully_processed_command_key = "successfully_processed_command" def __init__(self, channel, temperature_servo, oled): self.temperature_servo = temperature_servo self.oled = oled self.channel = channel # Do not forget to replace the string with your publish key publish_key = "pub-c-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Subscribe key is the one that usually starts with the "sub-c" prefix # Do not forget to replace the string with your subscribe key subscribe_key = "sub-c-xxxxxxxx-xxxx-xxxx-xxxx- xxxxxxxxxxxx" self.pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key) self.pubnub.subscribe(channels=self.channel, callback=self.callback, error=self.callback, connect=self.connect, reconnect=self.reconnect, disconnect=self.disconnect) def callback_response_message(self, message): print("I've received the following response from PubNub cloud: {0}".format(message)) def error_response_message(self, message): print("There was an error when working with the PubNub cloud: {0}".format(message)) def publish_response_message(self, message): response_message = { self.__class__.successfully_processed_command_key: message[self.__class__.command_key]} self.pubnub.publish( channel=self.channel, message=response_message, callback=self.callback_response_message, error=self.error_response_message) def callback(self, message, channel): if channel == self.channel: print("I've received the following message: {0}".format(message)) if self.__class__.command_key in message: if message[self.__class__.command_key] == "print_temperature_fahrenheit": self.temperature_servo.print_temperature (message["temperature_fahrenheit"]) self.publish_response_message(message) elif message[self.__class__.command_key] == "print_information_message": self.oled.print_line(11, message["text"]) self.publish_response_message(message) def error(self, message): print("Error: " + str(message)) def connect(self, message): print("Connected to the {0} channel". format(self.channel)) print(self.pubnub.publish( channel=self.channel, message="Listening to messages in the Intel Galileo Gen 2 board")) def reconnect(self, message): print("Reconnected to the {0} channel". format(self.channel)) def disconnect(self, message): print("Disconnected from the {0} channel". format(self.channel)) The highlighted lines in the previous code for the new version of the MessageChannel class show the changes we made in the code. First, the code declares the successfully_processed_command_key class attribute that defines the key string that defines what the code will use as a successfully processed command key in a response message published to the channel. Whenever we publish a message that includes the specified key string, we know that the value associated to this key in the dictionary will indicate the command that the board has successfully processed. The code declares the following three new methods: callback_response_message: This method will be used as the callback that will be executed when a successfully processed command response message is published to the channel. The method just prints the formatted response that PubNub returns when a message has been successfully published in the channel. In this case, the message argument doesn't hold the original message that has been published, it holds the formatted response. We use message for the argument name to keep consistency with the PubNub API. error_response_message: This method will be used as the callback that will be executed when an error occurs when trying to publish a successfully processed command response message to the channel. The method just prints the error message that PubNub returns when a message hasn't been successfully published in the channel. publish_response_message: This method receives the message with the command that was successfully processed in the message argument. The code creates a response_message dictionary with the successfully_processed_command_key class attribute as the key and the value of the key specified in the command_key class attribute for the message dictionary as the value. Then, the code calls the self.pubnub.publish method to publish the response_message dictionary to the channel saved in the channel attribute. The call to this method specifies self.callback_response_message as the callback to be executed when the message is successfully published and self.error_response_message as the callback to be executed when an error occurred during the publishing process. When we specify a callback, the publish method works with an asynchronous execution, and therefore, the execution is non-blocking. The publication of the message and the callbacks that are specified will run in a different thread. Now, the callback method defined in the MessageChannel class adds a call to the publish_response_message method with the message that included the command that has been successfully processed (message) as an argument. As previously explained, the publish_response_message method is non-blocking and will return immediately while the successfully processed message is published in another thread. Now, it is time to start running the example in the Intel Galileo Gen 2 board. The following line will start the example in the SSH console. python iot_python_chapter_09_03.py After you run the example, go to the Web browser in which you are working with the PubNub debug console. You will see the following message listed in the previously created client: "Listening to messages in the Intel Galileo Gen 2 board" Enter the following JSON code and click SEND: {"command":"print_temperature_fahrenheit", "temperature_fahrenheit": 90 } After you click SEND, the following lines will appear in the client log. The last message was published by the board to the channel indicates that the print_temperature_fahrenheit command has been successfully processed. [1,"Sent","14595406989121047"] { "command": "print_temperature_fahrenheit", "temperature_fahrenheit": 90 } { "successfully_processed_command": "print_temperature_fahrenheit" } The following picture shows the messages and debug messages log for the PubNub client after we clicked the SEND button: After you publish the previous message, you will see the following output in the SSH console for the Intel Galileo Gen 2 board. You will notice the servo's shaft rotates to 90 degrees. The board also receives the successfully processed command message because it is subscribed to the channel in which the message has been published. I've received the following message: {u'command': u'print_temperature_fahrenheit', u'temperature_fahrenheit': 90} I've received the following response from PubNub cloud: [1, u'Sent', u'14595422426124592'] I've received the following message: {u'successfully_processed_command': u'print_temperature_fahrenheit'} Now, enter the following JSON code and click SEND: {"command":"print_information_message", "text": "2nd message"} After you click Send, the following lines will appear in the client log. The last message published by the board to the channel indicates that the print_information_message command has been successfully processed. [1,"Sent","14595434708640961"] { "command": "print_information_message", "text": "2nd message" } { "successfully_processed_command": "print_information_message" } The following picture shows the messages and debug messages log for the PubNub client after we clicked the SEND button: After you publish the previous message, you will see the following output in the SSH console for the Intel Galileo Gen 2 board. You will see the following text displayed at the bottom of the OLED matrix: 2nd message. The board also receives the successfully processed command message because it is subscribed to the channel in which the message has been published. I've received the following message: {u'text': u'2nd message', u'command': u'print_information_message'} 2nd message I've received the following response from PubNub cloud: [1, u'Sent', u'14595434710438777'] I've received the following message: {u'successfully_processed_command': u'print_information_message'} We can work with the different SDKs provided by PubNub to subscribe and publish to a channel. We can also make different IoT devices talk to themselves by publishing messages to channels and processing them. In this case, we just created a few commands and we didn't add detailed information about the device that has to process the command or the device that has generated a specific message. A more complex API would require commands that include more information and security. Publishing messages to the cloud with a Python PubNub client So far, we have been using the PubNub debug console to publish messages to the temperature channel and make the Python code running in the Intel Galileo Gen 2 board process them. Now, we are going to code a Python client that will publish messages to the temperature channel. This way, we will be able to design applications that can talk to IoT devices with Python code in the publisher and in the subscriber devices. We can run the Python client on another Intel Galileo Gen 2 board or in any device that has Python 2.7.x installed. In addition, the code will run with Python 3.x. For example, we can run the Python client in our computer. We just need to make sure that we install the pubnub module we have previously installed with pip in the Python version that is running in the Yocto Linux for the board. We will create a Client class to represent a PubNub client, configure the PubNub subscription, make it easy to publish a message with a command and the required values for the command and declare the code for the callbacks that are going to be executed when certain events are fired. The code file for the sample is iot_python_chapter_09_04.py (you will find this in the code bundle). Don't forget to replace the strings assigned to the publish_key and subscribe_key local variables in the __init__ method with the values you have retrieved from the previously explained PubNub key generation process. The following lines show the code for the Client class: import time from pubnub import Pubnub class Client: command_key = "command" def __init__(self, channel): self.channel = channel # Publish key is the one that usually starts with the "pub-c-" prefix publish_key = "pub-c-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Subscribe key is the one that usually starts with the "sub-c" prefix # Do not forget to replace the string with your subscribe key subscribe_key = "sub-c-xxxxxxxx-xxxx-xxxx-xxxx- xxxxxxxxxxxx" self.pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key) self.pubnub.subscribe(channels=self.channel, callback=self.callback, error=self.callback, connect=self.connect, reconnect=self.reconnect, disconnect=self.disconnect) def callback_command_message(self, message): print("I've received the following response from PubNub cloud: {0}".format(message)) def error_command_message(self, message): print("There was an error when working with the PubNub cloud: {0}".format(message)) def publish_command(self, command_name, key, value): command_message = { self.__class__.command_key: command_name, key: value} self.pubnub.publish( channel=self.channel, message=command_message, callback=self.callback_command_message, error=self.error_command_message) def callback(self, message, channel): if channel == self.channel: print("I've received the following message: {0}".format(message)) def error(self, message): print("Error: " + str(message)) def connect(self, message): print("Connected to the {0} channel". format(self.channel)) print(self.pubnub.publish( channel=self.channel, message="Listening to messages in the PubNub Python Client")) def reconnect(self, message): print("Reconnected to the {0} channel". format(self.channel)) def disconnect(self, message): print("Disconnected from the {0} channel". format(self.channel)) The Client class declares the command_key class attribute that defines the key string that defines what the code understands as a command in the messages. Our main goal is to build and publish command messages to a specified channel. We have to specify the PubNub channel name in the channel-required argument. The constructor, that is, the __init__ method, saves the received argument in an attribute with the same name. We will be both a subscriber and a publisher for this channel. Then, the constructor declares two local variables: publish_key and subscribe_key. These local variables save the publish and subscribe keys we had generated with the PubNub Admin portal. Then, the code creates a new Pubnub instance with publish_key and subscribe_key as the arguments, and saves the reference for the new instance in the pubnub attribute. Finally, the code calls the subscribe method for the new instance to subscribe to data on the channel saved in the channel attribute. The call to this method specifies many methods declared in the Client class as we did for our previous examples. The publish_command method receives a command name, the key and the value that provide the necessary information to execute the command in the command_name, key and value required arguments. In this case, we don't target the command to a specific IoT device and all the devices that subscribe to the channel and run the code in our previous example will process the commands that we publish. We can use the code as a baseline to work with more complex examples in which generate commands that target specific IoT devices. Obviously, it is also necessary to improve the security. The method creates a dictionary and saves it in the command_message local variable. The command_key class attribute is the first key for the dictionary and the command_name received as an argument, the value that composes the first key-value pair. Then, the code calls the self.pubnub.publish method to publish the command_message dictionary to the channel saved in the channel attribute. The call to this method specifies self.callback_command_message as the callback to be executed when the message is published successfully and self.error_command_message as the callback to be executed when an error occurred during the publishing process. As happened in our previous example, when we specify a callback, the publish method works with an asynchronous execution. Now, we will use the previously coded Client class to write a __main__ method that uses the PubNub cloud to publish two commands that our board will process. The following lines show the code for the __main__ method. The code file for the sample is iot_python_chapter_09_04.py (you will find this in the code bundle). if __name__ == "__main__": client = Client("temperature") client.publish_command( "print_temperature_fahrenheit", "temperature_fahrenheit", 45) client.publish_command( "print_information_message", "text", "Python IoT" ) # Sleep 60 seconds (60000 milliseconds) time.sleep(60) The code in the __main__ method is very easy to understand. The code creates an instance of the Client class with "temperature" as an argument to become both a subscriber and a publisher for this channel in the PubNub cloud. The code saves the new instances in the client local variable. The code calls the publish_command method with the necessary arguments to build and publish the print_temperature_fahrenheit command with a temperature value of 45. The method will publish the command with an asynchronous execution. Then, the code calls the publish_command method again with the necessary arguments to build and publish the print_information_message command with a text value of "Python IoT". The method will publish the second command with an asynchronous execution. Finally, the code sleeps for 1 minute (60 seconds) in order to make it possible for the asynchronous executions to publish the commands successfully. The different callbacks defined in the Client class will be executed as the different events fire. As we are also subscribed to the channel, we will also receive the messages we publish in the temperature channel. Keep the Python code we executed in our previous example running on the board. We want the board to process our commands. In addition, keep the Web browser in which you are working with the PubNub debug console opened because we also want to see all the messages in the log. The following line will start the example for the Python client in any computer or device that you want to use as a client. It is possible to run the code in another SSH terminal in case you want to use the same board as a client. python iot_python_chapter_09_04.py After you run the example, you will see the following output in the Python console that runs the Python client, that is, the iot_python_chapter_09_04.py (you will find this in the code bundle)Python script. Connected to the temperature channel I've received the following response from PubNub cloud: [1, u'Sent', u'14596508980494876'] I've received the following response from PubNub cloud: [1, u'Sent', u'14596508980505581'] [1, u'Sent', u'14596508982165140'] I've received the following message: {u'text': u'Python IoT', u'command': u'print_information_message'} I've received the following message: {u'command': u'print_temperature_fahrenheit', u'temperature_fahrenheit': 45} I've received the following message: Listening to messages in the PubNub Python Client I've received the following message: {u'successfully_processed_command': u'print_information_message'} I've received the following message: {u'successfully_processed_command': u'print_temperature_fahrenheit'} The code used the PubNub Python SDK to build and publish the following two command messages in the temperature channel: {"command":"print_temperature_fahrenheit", "temperature_fahrenheit": "45"} {"command":"print_information_message", "text": "Python IoT"} As we are also subscribed to the temperature channel, we receive the messages we sent with an asynchronous execution. Then, we received the successfully processed command messages for the two command messages. The board has processed the commands and published the messages to the temperature channel. After you run the example, go to the Web browser in which you are working with the PubNub debug console. You will see the following messages listed in the previously created client: [1,"Subscribed","temperature"] "Listening to messages in the Intel Galileo Gen 2 board" { "text": "Python IoT", "command": "print_information_message" } { "command": "print_temperature_fahrenheit", "temperature_fahrenheit": 45 } "Listening to messages in the PubNub Python Client" { "successfully_processed_command": "print_information_message" } { "successfully_processed_command": "print_temperature_fahrenheit" } The following picture shows the last messages displayed in the log for the PubNub client after we run the previous example: You will see the following text displayed at the bottom of the OLED matrix: Python IoT. In addition, the servo's shaft will rotate to 45 degrees. We can use the PubNub SDKs available in different programming languages to create applications and apps that publish and receive messages in the PubNub cloud and interact with IoT devices. In this case, we worked with the Python SDK to create a client that publishes commands. It is possible to create mobile apps that publish commands and easily build an app that can interact with our IoT device. Summary In this article, we combined many cloud-based services that allowed us to easily publish data collected from sensors and visualize it in a Web-based dashboard. We realized that there is always a Python API, and therefore, it is easy to write Python code that interacts with popular cloud-based services. Resources for Article: Further resources on this subject: Internet of Things with BeagleBone[article] The Internet of Things[article] Python Data Structures[article]
Read more
  • 0
  • 0
  • 1639

article-image-working-webcam-and-pi-camera
Packt
09 Feb 2016
13 min read
Save for later

Working with a Webcam and Pi Camera

Packt
09 Feb 2016
13 min read
In this article by Ashwin Pajankar and Arush Kakkar, the author of the book Raspberry Pi By Example we will learn how to use different types and uses of cameras with our Pi. Let's take a look at the topics we will study and implement in this article: Working with a webcam Crontab Timelapse using a webcam Webcam video recording and playback Pi Camera and Pi NOIR comparison Timelapse using Pi Camera The PiCamera module in Python (For more resources related to this topic, see here.) Working with webcams USB webcams are a great way to capture images and videos. Raspberry Pi supports common USB webcams. To be on the safe side, here is a list of the webcams supported by Pi: http://elinux.org/RPi_USB_Webcams. I am using a Logitech HD c310 USB Webcam. You can purchase it online, and you can find the product details and the specifications at http://www.logitech.com/en-in/product/hd-webcam-c310. Attach your USB webcam to Raspberry Pi through the USB port on Pi and run the lsusb command in the terminal. This command lists all the USB devices connected to the computer. The output should be similar to the following output depending on which port is used to connect the USB webcam:   pi@raspberrypi ~/book/chapter04 $ lsusb Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 148f:2070 Ralink Technology, Corp. RT2070 Wireless Adapter Bus 001 Device 007: ID 046d:081b Logitech, Inc. Webcam C310 Bus 001 Device 006: ID 1c4f:0003 SiGma Micro HID controller Bus 001 Device 005: ID 1c4f:0002 SiGma Micro Keyboard TRACER Gamma Ivory Then, install the fswebcam utility by running the following command: sudo apt-get install fswebcam The fswebcam is a simple command-line utility that captures images with webcams for Linux computers. Once the installation is done, you can use the following command to create a directory for output images: mkdir /home/pi/book/output Then, run the following command to capture the image: fswebcam -r 1280x960 --no-banner ~/book/output/camtest.jpg This will capture an image with a resolution of 1280 x 960. You might want to try another resolution for your learning. The --no-banner command will disable the timestamp banner. The image will be saved with the filename mentioned. If you run this command multiple times with the same filename, the image file will be overwritten each time. So, make sure that you change the filename if you want to save previously captured images. The text output of the command should be similar to the following: --- Opening /dev/video0... Trying source module v4l2... /dev/video0 opened. No input was specified, using the first. --- Capturing frame... Corrupt JPEG data: 2 extraneous bytes before marker 0xd5 Captured frame in 0.00 seconds. --- Processing captured image... Disabling banner. Writing JPEG image to '/home/pi/book/output/camtest.jpg'. Crontab A cron is a time-based job scheduler in Unix-like computer operating systems. It is driven by a crontab (cron table) file, which is a configuration file that specifies shell commands to be run periodically on a given schedule. It is used to schedule commands or shell scripts to run periodically at a fixed time, date, or interval. The syntax for crontab in order to schedule a command or script is as follows: 1 2 3 4 5 /location/command Here, the following are the definitions: 1: Minutes (0-59) 2: Hours (0-23) 3: Days (0-31) 4: Months [0-12 (1 for January)] 5: Days of the week [0-7 ( 7 or 0 for Sunday)] /location/command: The script or command name to be scheduled The crontab entry to run any script or command every minute is as follows: * * * * * /location/command 2>&1 In the next section, we will learn how to use crontab to schedule a script to capture images periodically in order to create the timelapse sequence. You can refer to this URL for more details oncrontab: http://www.adminschoice.com/crontab-quick-reference. Creating a timelapse sequence using fswebcam Timelapse photography means capturing photographs in regular intervals and playing the images with a higher frequency in time than those that were shot. For example, if you capture images with a frequency of one image per minute for 10 hours, you will get 600 images. If you combine all these images in a video with 30 images per second, you will get 10 hours of timelapse video compressed in 20 seconds. You can use your USB webcam with Raspberry Pi to achieve this. We already know how to use the Raspberry Pi with a Webcam and the fswebcam utility to capture an image. The trick is to write a script that captures images with different names and then add this script in crontab and make it run at regular intervals. Begin with creating a directory for captured images: mkdir /home/pi/book/output/timelapse Open an editor of your choice, write the following code, and save it as timelapse.sh: #!/bin/bash DATE=$(date +"%Y-%m-%d_%H%M") fswebcam -r 1280x960 --no-banner /home/pi/book/output/timelapse/garden_$DATE.jpg Make the script executable using: chmod +x timelapse.sh This shell script captures the image and saves it with the current timestamp in its name. Thus, we get an image with a new filename every time as the file contains the timestamp. The second line in the script creates the timestamp that we're using in the filename. Run this script manually once, and make sure that the image is saved in the /home/pi/book/output/timelapse directory with the garden_<timestamp>.jpg name. To run this script at regular intervals, we need to schedule it in crontab. The crontab entry to run our script every minute is as follows: * * * * * /home/pi/book/chapter04/timelapse.sh 2>&1 Open the crontab of the Pi user with crontab –e. It will open crontab with nano as the editor. Add the preceding line to crontab, save it, and exit it. Once you exit crontab, it will show the following message: no crontab for pi - using an empty one crontab: installing new crontab Our timelapse webcam setup is now live. If you want to change the image capture frequency, then you have to change the crontab settings. To set it every 5 minutes, change it to */5 * * * *. To set it for every 2 hours, use 0 */2 * * *. Make sure that your MicroSD card has enough free space to store all the images for the time duration for which you need to keep your timelapse setup. Once you capture all the images, the next part is to encode them all in a fast playing video, preferably 20 to 30 frames per second. For this part, the mencoder utility is recommended. The following are the steps to create a timelapse video with mencoder on a Raspberry Pi or any Debian/Ubuntu machine: Install mencoder using sudo apt-get install mencoder. Navigate to the output directory by issuing: cd /home/pi/book/output/timelapse Create a list of your timelapse sequence images using: ls garden_*.jpg > timelapse.txt Use the following command to create a video: mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1280:960 -o timelapse.avi -mf type=jpeg:fps=30 mf://@timelapse.txt This will create a video with name timelapse.avi in the current directory with all the images listed in timelapse.txt with a 30 fps frame rate. The statement contains the details of the video codec, aspect ratio, bit rate, and scale. For more information, you can run man mencoder on Command Prompt. We will cover how to play a video in the next section. Webcam video recording and playback We can use a webcam to record live videos using avconv. Install avconv using sudo apt-get install libav-tools. Use the following command to record a video: avconv -f video4linux2 -r 25 -s 1280x960 -i /dev/video0 ~/book/output/VideoStream.avi It will show following output on the screen. pi@raspberrypi ~ $ avconv -f video4linux2 -r 25 -s 1280x960 -i /dev/video0 ~/book/output/VideoStream.avi avconv version 9.14-6:9.14-1rpi1rpi1, Copyright (c) 2000-2014 the Libav developers built on Jul 22 2014 15:08:12 with gcc 4.6 (Debian 4.6.3-14+rpi1) [video4linux2 @ 0x5d6720] The driver changed the time per frame from 1/25 to 2/15 [video4linux2 @ 0x5d6720] Estimating duration from bitrate, this may be inaccurate Input #0, video4linux2, from '/dev/video0': Duration: N/A, start: 629.030244, bitrate: 147456 kb/s Stream #0.0: Video: rawvideo, yuyv422, 1280x960, 147456 kb/s, 1000k tbn, 7.50 tbc Output #0, avi, to '/home/pi/book/output/VideoStream.avi': Metadata: ISFT : Lavf54.20.4 Stream #0.0: Video: mpeg4, yuv420p, 1280x960, q=2-31, 200 kb/s, 25 tbn, 25 tbc Stream mapping: Stream #0:0 -> #0:0 (rawvideo -> mpeg4) Press ctrl-c to stop encoding frame= 182 fps= 7 q=31.0 Lsize= 802kB time=7.28 bitrate= 902.4kbits/s video:792kB audio:0kB global headers:0kB muxing overhead 1.249878% Received signal 2: terminating. You can terminate the recording sequence by pressing Ctrl + C. We can play the video using omxplayer. It comes with the latest raspbian, so there is no need to install it. To play a file with the name vid.mjpg, use the following command: omxplayer ~/book/output/VideoStream.avi It will play the video and display some output similar to the one here: pi@raspberrypi ~ $ omxplayer ~/book/output/VideoStream.avi Video codec omx-mpeg4 width 1280 height 960 profile 0 fps 25.000000 Subtitle count: 0, state: off, index: 1, delay: 0 V:PortSettingsChanged: 1280x960@25.00 interlace:0 deinterlace:0 anaglyph:0 par:1.00 layer:0 have a nice day ;) Try playing timelapse and record videos using omxplayer. Working with the Pi Camera and NoIR Camera Modules These camera modules are specially manufactured for Raspberry Pi and work with all the available models. You will need to connect the camera module to the CSI port, located behind the Ethernet port, and activate the camera using the raspi-config utility if you haven't already. You can find the video instructions to connect the camera module to Raspberry Pi at http://www.raspberrypi.org/help/camera-module-setup/. This page lists the types of camera modules available: http://www.raspberrypi.org/products/. Two types of camera modules are available for the Pi. These are Pi Camera and Pi NoIR camera, and they can be found at https://www.raspberrypi.org/products/camera-module/ and https://www.raspberrypi.org/products/pi-noir-camera/, respectively. The following image shows Pi Camera and Pi NoIR Camera boards side by side: The following image shows the Pi Camera board connected to the Pi: The following is an image of the Pi camera board placed in the camera case: The main difference between Pi Camera and Pi NoIR Camera is that Pi Camera gives better results in good lighting conditions, whereas Pi NoIR (NoIR stands for No-Infra Red) is used for low light photography. To use NoIR Camera in complete darkness, we need to flood the object to be photographed with infrared light. This is a good time to take a look at the various enclosures for Raspberry Pi Models. You can find various cases available online at https://www.adafruit.com/categories/289. An example of a Raspberry Pi case is as follows: Using raspistill and raspivid To capture images and videos using the Raspberry Pi camera module, we need to use raspistill and raspivid utilities. To capture an image, run the following command: raspistill -o cam_module_pic.jpg This will capture and save the image with name cam_module_pic.jpg in the current directory. To capture a 20 second video with the camera module, run the following command: raspivid –o test.avi –t 20000 This will capture and save the video with name test.avi in the current directory. Unlike fswebcam and avconv, raspistill and raspivid do not write anything to the console. So, you need to check the current directory for the output. Also, one can run the echo $? command to check whether these commands executed successfully. We can also mention the complete location of the file to be saved in these command, as shown in the following example: raspistill -o /home/pi/book/output/cam_module_pic.jpg Just like fswebcam, raspistill can be used to record the timelapse sequence. In our timelapse shell script, replace the line that contains fswebcam with the appropriate raspistill command to capture the timelapse sequence and use mencoder again to create the video. This is left as an exercise for the readers. Now, let's take a look at the images taken with the Pi camera under different lighting conditions. The following is the image with normal lighting and the backlight: The following is the image with only the backlight: The following is the image with normal lighting and no backlight: For NoIR camera usage in the night under low light conditions, use IR illuminator light for better results. You can get it online. A typical off-the-shelf LED IR illuminator suitable for our purpose will look like the one shown here: Using picamera in Python with the Pi Camera module picamera is a Python package that provides a programming interface to the Pi Camera module. The most recent version of raspbian has picamera preinstalled. If you do not have it installed, you can install it using: sudo apt-get install python-picamera The following program quickly demonstrates the basic usage of the picamera module to capture an image: import picamera import time with picamera.PiCamera() as cam: cam.resolution=(1024,768) cam.start_preview() time.sleep(5) cam.capture('/home/pi/book/output/still.jpg') We have to import time and picamera modules first. cam.start_preview()will start the preview, and time.sleep(5) will wait for 5 seconds before cam.capture() captures and saves image in the specified file. There is a built-in function in picamera for timelapse photography. The following program demonstrates its usage: import picamera import time with picamera.PiCamera() as cam: cam.resolution=(1024,768) cam.start_preview() time.sleep(3) for count, imagefile in enumerate(cam.capture_continuous ('/home/pi/book/output/image{counter: 02d}.jpg')): print 'Capturing and saving ' + imagefile time.sleep(1) if count == 10: break In the preceding code, cam.capture_continuous()is used to capture the timelapse sequence using the Pi camera module. Checkout more examples and API references for the picamera module at http://picamera.readthedocs.org/. The Pi camera versus the webcam Now, after using the webcam and the Pi camera, it's a good time to understand the differences, the pros, and the cons of using these. The Pi camera board does not use a USB port and is directly interfaced to the Pi. So, it provides better performance than a webcam in terms of the frame rate and resolution. We can directly use the picamera module in Python to work on images and videos. However, the Pi camera cannot be used with any other computer. A webcam uses an USB port for interface, and because of that, it can be used with any computer. However, compared to the Pi camera its performance, it is lower in terms of the frame rate and resolution. Summary In this article, we learned how to use a webcam and the Pi camera. We also learned how to use utilities such as fswebcam, avconv, raspistill, raspivid, mencoder, and omxplayer. We covered how to use crontab. We used the Python picamera module to programmatically work with the Pi camera board. Finally, we compared the Pi camera and the webcam. We will be reusing all the code examples and concepts for some real-life projects soon. Resources for Article: Further resources on this subject: Introduction to the Raspberry Pi's Architecture and Setup [article] Raspberry Pi LED Blueprints [article] Hacking a Raspberry Pi project? Understand electronics first! [article]
Read more
  • 0
  • 0
  • 33399

article-image-heart-it-all
Packt
27 Jan 2016
15 min read
Save for later

The Heart of It All

Packt
27 Jan 2016
15 min read
In this article by Thomas Hamilton, the author of Building a Media Center with Raspberry Pi ,you will learn how to find the operating system that you will use on the system that you chose. Just like with hardware, there are a plethora of options for the operating systems for the Raspberry Pi. For this book, we are going to focus on transforming the Raspberry Pi into a media center. At the time of writing this book, there are two operating systems available that are well known for being geared specifically to do just this. The first one is called the Open Embedded Linux Entertainment Center (openELEC) and is a slimmed-down operating system that has been optimized to be a media center and nothing else. The second option, and the one that we will be using for this project, is called the Open Source Media Center (OSMC). The main advantage of this specific version is that there is a full operating system running in the background. This will be important for some of the add-ons to work correctly. Once you can do this, if you want to try openELEC, you will be fully prepared to be able to do this on your own. In fact, the information in this article will enable you to install practically any operating system that's designed for a Raspberry Pi onto an SD card for you to use and experiment with as you see fit. In this article, we will cover the following topics: Downloading an operating system Installing an operating system to an SD card using Windows Install an operating system to an SD card using Linux (For more resources related to this topic, see here.) The Operating System It is now time to find the correct version of OSMC so that we can download and install it. If you are primarily a Windows or an iOS user, it may feel strange to think that you can search online for operating systems and just download them to your computer. In the Linux world, the world in which the Raspberry Pi resides, this is very normal and one of the great things about open source. The Raspberry Pi is built as a learning tool. It was designed in such a way that it will allow you to modify and add to it. In this way, the community can develop it and make it better. Open source software does the same thing. If you know programming, you can contribute to and change software that someone else developed, and this is encouraged! More eyes on the code means less bugs and vulnerabilities. Most versions of Linux follow this open source principle. Versions of Linux? Yes. This is another point of confusion for Windows and Mac users. For the computers that you buy in a normal retail or computer store, you do not have many choices related to the OS that is already installed. You can either buy an Apple product with the newest version of their OS, or a Windows-based computer with Windows 7, 8, or 10 pre-installed. In this example, Windows 7, 8, and 10 are just newer and older versions of each other. Linux works off a different principle. Linux itself is not an operating system. Think of it more like a type of operating system or maybe as a brand such as Microsoft and Apple. Because it is open source and free, developers can take it and turn it into whatever they need it to be. The most popular versions of Linux are Ubuntu, Fedora, Suse, Mint, and CentOS. They each have a different look and feel and can have different functions. They are also operating systems that can be used daily for your normal computing needs. This article is based on a combination of Ubuntu and Fedora operating systems. The world of Linux and open source software can be confusing at first. Don't be scared! After you get past the shock, you will find that this openness is very exciting and helpful and can actually make your life much easier. Now, lets download OSMC. Raspberrypi.org If you haven't come across this already, it is the official website for the Raspberry Pi. From this website, you can find information about the Raspberry Pi, instructional how-tos and forums to talk with other Raspberry Pi users. This site can point you to their official retailers for the versions of the Raspberry Pi that are currently in production, and for the purpose of this article, it points us to the most popular operating systems for the Raspberry Pi (though not nearly all the ones that can work on it). From the main page, click on the link that says DOWNLOADS near the top of the page. This will bring you to the page that lists the most popular operating systems. Raspbian is the official OS of the Raspberry Pi and what OSMC is based on. Noobs is worth looking at for your next project. It isn't an OS itself, but it gives you the ability to choose from a list of operating systems and install them with a single click. If you want to see what the Raspberry Pi is capable of, start with Noobs. Under these options, you will have a list of third-party operating systems. The names may sound familiar at this point, as we have mentioned most of them already. This list is where you will find OSMC. Click on its link to go to their website. We could have gone straight to this website to download OSMC, but this allowed you to see what other options are available and which is the easiest place to find them. OSMC gives a few different ways to install the OS onto different types of computers. If you want to use their automated way of installing OSMC to an SD card for the Raspberry Pi, you are welcome to do so; just follow their instructions for the operation system that you are using on your main computer. For learning purposes, I am going to explain the method of downloading a disk image and doing it ourselves, as this is how most operating systems are installed to the Raspberry Pi. Under the heading named Get Started, where you can choose the automated installation methods, there is a line just under it that allows you to download disk images. This is what we are going to do. Click on that link. Now, we are presented with choices, namely Raspberry Pi 1 and Raspberry Pi 2. The Raspberry Pi 1 refers to any of the single-core Raspberry Pi devices while the Raspberry Pi 2 refers to the newest Pi with a quad-core processor and more RAM. Click on the link under whichever heading applies for the type of Pi that you will be using and select the newest release option that is available. Verifying the download While OSMC is downloading, let's take a minute to understand what the MD5 Checksum is. An MD5 Checksum is used to verify a file's integrity. The number that you see beside the download is the Checksum that was created when the file that you are downloading was created. After the image has finished downloading, we will check the MD5 Checksum of the file on your computer as well. These numbers should be identical. If they are not, it indicates that the image is corrupt and you will need to download it again. From a security standpoint, a checksum can also be used to ensure that data hasn't been tampered with in the time span between when it was created and when it was given to you. This could indicate malicious software or a data breech. Now that OSMC has been downloaded, we can verify its integrity. In Linux, this is easy. Open a terminal and navigate to the Downloads folder or wherever you downloaded the file. Now type in the following command: [md5sum name-of-file] The output that this gives should match the MD5 Checksum that was beside the file that you clicked on to download. If it doesn't, delete the file and try doing this again. To verify the file integrity using Windows, you will need to install a program that can do this. Search online for MD5 checksum Windows, and you will see that Microsoft has a program that can be downloaded from their website. Once you download and install it, it will work in a fashion that's similar to the Linux method, where you use the Windows command prompt. It comes with a readme file to explain how to use it. If you are unable to find a program to verify the checksum, do not worry. This step isn't required, but it helps you troubleshoot whether the Raspberry Pi will not boot after you install the OS onto the SD card. Installing OSMC - for Windows users For Windows, you need to install two more applications to successfully write OSMC to an SD card. Because the OSMC file that you downloaded is compressed using gzip, you need a program that can unzip it. The recommended program for all of your compression needs in Windows is WinRAR. It is free and can be found at www.filehippo.com along with the next program that you will need. After you unzip the OSMC file, you will need a program that can write (burn) it to your SD card. There are many options to choose from, and these options can be found under the CD/DVD option of Categories on the homepage. ImgBurn and DeepBurner appear to be the most popular image burning software at the time of writing this article. Preparing everything Ensure that you have the appropriate type of SD card for the Raspberry Pi that you own. The original Raspberry Pi Model A and B use full-size SD cards. Thus, if you purchased a miniSD by mistake, do not worry. The miniSD probably came with an adapter that turns it into a full-size SD. If it did not, they are easy to acquire. You will need to insert your SD card into your computer so that you can write the operating system on it. If your computer has an in-built SD card reader, then that is ideal. If it does not, there are card readers available that plug in through your USB port and which can accomplish this goal as well. Once you have inserted your SD card into your computer using either method, ensure that you have taken all the information off the card that you want to keep. Anything that's currently on the card will be erased in the following steps! Install WinRAR and your image burning program if you have not already done so. When it is , you should be able to right-click on the OSMC file that you downloaded and select the option to uncompress or extract the files in a gzip file. Burn It! Now that we have an OSMC file that ends with .img, we can open the image burning program. Each program works differently, but you want to set the destination (where the image will be burned) as your SD card and the source (or input file) as the OSMC image. Once these settings are correct, click on BurnISO to begin burning the image. Now that this is done, congratulations! Installing OSMC - for Linux users As you have seen several times already, Linux comes with nearly everything that you need already installed. The software used to install the operating system to the SD card is no different. Ensure that you have the appropriate type of the SD card for the Raspberry Pi that you own. The original Raspberry Pi Model A and B use full-size SD cards. Therefore, if you purchased a miniSD by mistake, do not worry. The miniSD probably came with an adapter that turns it into a full-size SD. If it did not, they are easy to acquire. Preparing the SD card You will need to insert your SD card into your computer so that you can write the operating system on it. If your computer has an in-built SD card reader, then that is ideal. If it does not, there are card readers available that plug in through your USB port that can accomplish this goal as well. Once you have inserted your SD card into your computer using either method, ensure that you have taken all information that you want to keep off the card. Anything that's currently on the card will be erased in the next step! If the SD card was already formatted with a filesystem, it probably automounted itself somewhere so that you can access it. We need to unmount it so that the system is not actually using it, but it is still inserted into the computer. To do this, type the following command into your command line: lsblk This command lists the block devices that are currently on your computer. In other words, it shows the storage devices and the partitions on them. Sda is most likely your hard drive; you can tell by the size of the device in the right columns. Sda1 and sda2 are the partitions on the sda device. Look for your device by its size. If you have a 4 GB SD card, then you will see something like this: NAME                    MAJ:MIN RM   SIZE    RO TYPE  MOUNTPOINT sda                          8:0          0     238.5G  0   disk  ├─sda1                      8:1          0     476M  0   part    /boot └─sda2                       8:2          0      186.3G  0   part    / sdb                          8:16        1      3.8G  0   disk  ├─sdb1                       8:17        1      2.5G   0  part   └─sdb2                       8:18        1      1.3G   0  part    /run/media/username/mountpoint In this case, my SD card is sdb and the second partition is mounted. To unmount this, we are going to issue the following command in the terminal again: sudo umount /dev/sdb* It will then ask you for your sudo (administrator) password and then unmount all the partitions for the sdb device. In this case, you could have replaced the sdb* with the partition number (sdb2) to be more specific if you only wanted to unmount one partition and not the entire device. In this example, we will erase everything on the device so that we unmount everything. Now, we can write the operating system to the SD card. Burn It! The process of installing an OSMC to the SD card is called burning an image. The process of burning an image is done with a program called dd, and it is done via the terminal. dd is a very useful tool that's used to copy disks and partitions to other disks or partitions or to images and vice versa. In this instance, we will take an image and copy it to a disk. In the terminal, navigate to the directory where you downloaded OSMC. The file that you downloaded is compressed using gzip. Before we can burn it to the disk, we need to unzip it. To do so, type in the following command: gunzip name-of-file.img.gz This will leave you with a new file that has the same name but with the .gz file no longer at the end. This file is also much bigger than the gzipped version. This .img (image) file is what we will burn to the SD card. In the previous step, we found out what device our SD card was listed under (it was sdb in the preceding example) and unmounted it. Now, we are going to use the following command to burn the image: sudo dd if=name-of-file.img of=/dev/sdb  (change /dev/sdb to whatever it is on your computer)  And that's it! This will take several minutes to complete and the terminal will look like it froze, but this is because it is working. When it is done, the prompt will come back and you can remove the SD card: Summary If your computer already uses Linux, these steps will be a little bit faster because you already have the needed software. For Windows users, hunting for the right software and installing it will take some time. Just have patience and know that the exciting part is just around the corner. Now that we have downloaded OSMC, verified the download, prepared the SD card, and burned OSMC on it, the hardest part is over. Resources for Article:   Further resources on this subject: Raspberry Pi LED Blueprints [article] Raspberry Pi and 1-Wire [article] Raspberry Pi Gaming Operating Systems [article]
Read more
  • 0
  • 0
  • 1377

article-image-debugging-applications-pdb-and-log-files
Packt
23 Sep 2015
13 min read
Save for later

Debugging Applications with PDB and Log Files

Packt
23 Sep 2015
13 min read
 In this article by Dan Nixon of the book Getting Started with Python and Raspberry Pi, we will learn more about how to debug Python code using the Python Debugger (PDB) tool and how we can use the Python logging framework to make complex applications written in Python easier to debug when they fail. (For more resources related to this topic, see here.) We will also look at the technique of unit testing and how the unittest Python module can be used to test small sections of a Python application to ensure that it is functioning as expected. These techniques are commonly used in applications written in other languages and are good skills to learn if you are often going to be developing applications. The Python debugger PDB is a tool that allows real time debugging of running Python code. It can help to track down issues with the logic of a program to help find the cause of a crash or unexpected behavior. PDB can be launched with the following command: pdb2.7 do_calculaton.py This will open a new PDB shell, as shown in the following screenshot: We can use the continue command (which can be shortened to c) to execute the next section of the code until a breakpoint is hit. As we are yet to declare any breakpoints, this will run the script until it exits normally, as shown in the following screenshot: We can set breakpoints in the application, where the program will be stopped, and you will be taken back to the PDB shell in order to debug the control flow of the program. The easiest way to set a breakpoint is by giving a specific line in a file, for example: break Operation.py:7 This command will add a breakpoint on line 7 of Operation.py. When this is added, PDB will confirm the file and the line number, as shown in the following screenshot: Now, when we run the application, we will see the program stop each time the breakpoint is reached. When a breakpoint is reached, we can resume the program using the c command: When paused at a breakpoint, we can view the details of the local variables in the current scope. For example, in the breakpoint we have added, there is a variable named name, which we can see the value of by using the following command: p name This outputs the value of the variable, as shown in the following screenshot: When at a breakpoint, we can also get a stack trace of the functions that have been called so far. This is done using the bt command and gives output like that shown in the following screenshot: We can also modify the values of the variables when paused at a breakpoint. To do this, simply assign a value to the variable name as you would in a regular Python script: name = 'subtract' In the following screenshot, this was used to change the first operation in the do_calculation.py script from add to subtract; the effect on the calculation is seen in the different result value: When at a breakpoint, we can also use the l command to see the current line the program is paused at. An example of this is shown in the following screenshot: We can also setup a series of commands to be executed when we hit a breakpoint. This can allow debugging to be automated to an extent by automatically recording or modifying the values of the variables at certain points in the program's execution. This can be demonstrated using the following commands on a new instance of PDB with no breakpoints set (first, quit PDB using the q command, and then re-launch it): break Operation.py:7 commands p name c This gives the following output. Note that the commands are entered on a terminal prefixed (com) rather than the PDB terminal prefixed (pdb). This set of commands tells PDB to print the value of the name variable and continue execution when the last added breakpoint was hit. This gives the output shown in the following screenshot: Within PDB, you can also use the ? command to get a full list of the available commands and help on using them, as shown in the following screenshot: Further information and full documentation on PDB is available at https://docs.python.org/2/library/pdb.html. Writing log files The next technique we will look at is having our application output a log file. This allows us to get a better understanding of what was happening at the time an application failed, which can provide key information into finding the cause of the failure, especially when the failure is being reported by a user of your application. We will add some logging statements to the Calculator.py and Operation.py files. To do this, we must first add the import for the logging module (https://docs.python.org/2/library/logging.html) to the start of each python file, which is simply: import logging In the Operation.py file, we will add two logging calls in the evaluate function, as shown in the following code: def evaluate(self, a, b): logging.getLogger(__name__).info("Evaluating operation: %s" % (self._operation)) logging.getLogger(__name__).debug("RHS: %f, LHS: %f" % (a, b)) This will output two logging statements: one at the debug level and one at the information level. There are in total five unique levels at which messages can be output. In increasing severity, they are: debug() info() warning() error() critical() Log handlers can be filtered to only process the log messages of a certain severity if required. We will see this in action later in this section. The logging.getLogger(__name__) call is used to retrieve the Logger class for the current module (where the name of the module is given by the __name__ variable). By default, each module uses its own Logger class identified by the name of the module. Next, we can add some debugging statements to the Calculator.py file in the same way. Here, we will add logging to the enter_value, enter_operation, evaluate, and all_clear functions, as shown in the following code snippet: def enter_value(self, value): if len(self._input_list) > 0 and not isinstance(self._input_list[-1], Operation): raise RuntimeError("Must enter an operation next") logging.getLogger(__name__).info("Adding value: %f" % (value)) self._input_list.append(float(value)) def enter_operation(self, operation_name): if len(self._input_list) == 0 or isinstance(self._input_list[-1], Operation): raise RuntimeError("Must enter a value next") logging.getLogger(__name__).info("Adding operation: %s" % (operation_name)) self._input_list.append(Operation(operation_name)) def evaluate(self): logging.getLogger(__name__).info("Evaluating calculation") if len(self._input_list) % 2 == 0: raise RuntimeError("Input length mismatch") self._result = self._input_list[0] for idx in range(1, len(self._input_list), 2): operation = self._input_list[idx] next_value = self._input_list[idx + 1] logging.getLogger(__name__).debug("Next function: %f %s %f" % ( self._result, str(operation), next_value)) self._result = operation.evaluate(self._result, next_value) logging.getLogger(__name__).info("Result is: %f" % (self._result)) return self._result def all_clear(self): logging.getLogger(__name__).info("Clearing calculator") self._input_list = [] self._result = 0.0 Finally, we need to configure a handler for the log messages. This is what will handle the messages sent by each logger and output them to a suitable destination; for example, the standard output or a file. We will configure this in the do_conversion.py file. First, we will configure a basic handler that will print all the log messages to the standard output so that they appear on the terminal. This can be achieved with the following code: logging.basicConfig(level=logging.DEBUG) We will also add the following line to the end of the script. This is used to close any open log handlers and should be included at the very end of an application (the logging framework should not be used after calling this function). logging.shutdown() Now, we can see the effects by running the script using the following command: python do_calculation.py This will give an output to the terminal, as shown in the following screenshot: We can also have the log output written to a file instead of printed to the terminal by adding a filename to the logger configuration. This helps to keep the terminal free of unnecessary information. logging.basicConfig(level=logging.DEBUG, filename='calc.log') When executed, this will give no additional output other than the result of the calculation, but will have created an additional file, calc.log, which contains the log messages, as shown in the following screenshot: Unit testing Unit testing is a technique for automated testing of small sections ("units") of code to ensure that the components of a larger application are working as intended, independently of each other. There are many frameworks for this in almost every language. In Python, we will be using the unittest module, as this is included with the language and is the most common framework used in the Python applications. To add unit tests to our calculator module, we will create an additional module in the same directory named test. Inside that will be three files: __init__.py (used to denote that a directory is a Python package), test_Calculator.py, and test_Operation.py. After creating this additional module, the structure of the code will be the same as shown in the following image: Next, we will modify the test_Operation.py file to include a test case for the Operation class. As always, this will start with the required imports for the modules we will be using: import unittest from calculator.Operation import Operation We will be creating a class, test_Operation, which inherits from the TestCase class provided by the unittest module. This contains the logic required to run the functions of the class as individual unit tests. class test_Operation(unittest.TestCase): Now, we will define four tests to test the creation of a new Operation instance for each of the operations that are supported by the class. Here, the assertEquals function is used to test for equality between two variables; this determines if the test passes or not. def test_create_add(self): op = Operation('add') self.assertEqual(str(op), 'add') def test_create_subtract(self): op = Operation('subtract') self.assertEqual(str(op), 'subtract') def test_create_multiply(self): op = Operation('multiply') self.assertEqual(str(op), 'multiply') def test_create_divide(self): op = Operation('divide') self.assertEqual(str(op), 'divide') In this test we are checking that a RuntimeError is raised when an unknown operation is given to the Operation constructor. We will do this using the assertRaises function. def test_create_fails(self): self.assertRaises(ValueError, Operation, 'not_a_function') Next, we will create four tests to ensure that each of the known operations evaluates to the correct result: def test_add(self): op = Operation('add') result = op.evaluate(5, 2) self.assertEqual(result, 7) def test_subtract(self): op = Operation('subtract') result = op.evaluate(5, 2) self.assertEqual(result, 3) def test_multiply(self): op = Operation('multiply') result = op.evaluate(5, 2) self.assertEqual(result, 10) def test_divide(self): op = Operation('divide') result = op.evaluate(5, 2) self.assertEqual(result, 2) This will form the test case for the Operation class. Typically, the test file for a module should have the name of the module prefixed by test, and the name of each test function within a test case class should start with test. Next, we will create a test case for the Calculator class in the test_Calculator.py file. This again starts by importing the required modules and defining the class: import unittest from calculator.Calculator import Calculator class test_Operation(unittest.TestCase): We will now add two test cases that test the correct handling of errors when operations and values are entered in the incorrect order. This time, we will use the assertRaises function to create a context to test for RuntimeError being raised. In this case, the error must be raised by any of the code within the context. def test_add_value_out_of_order_fails(self): with self.assertRaises(RuntimeError): calc = Calculator() calc.enter_value(5) calc.enter_value(5) calc.evaluate() def test_add_operation_out_of_order_fails(self): with self.assertRaises(RuntimeError): calc = Calculator() calc.enter_operation('add') calc.evaluate() This test is to ensure that the all_clear function works as expected. Note that, here, we have multiple test assertions in the function, and all assertions have to pass for the test to pass. def test_all_clear(self): calc = Calculator() calc.enter_value(5) calc.evaluate() self.assertEqual(calc.get_result(), 5) calc.all_clear() self.assertEqual(calc.get_result(), 0) This test ensured that the evaluate() function works as expected and checks the output of a known calculation. Note, here, that we are using the assertAlmostEqual function, which ensures that two numerical variables are equal within a given tolerance, in this case 13 decimal places. def test_evaluate(self): calc = Calculator() calc.enter_value(5.0) calc.enter_operation('multiply') calc.enter_value(2.0) calc.enter_operation('divide') calc.enter_value(5.0) calc.enter_operation('add') calc.enter_value(18.0) calc.enter_operation('subtract') calc.enter_value(5.0) self.assertAlmostEqual(calc.evaluate(), 15.0, 13) self.assertAlmostEqual(calc.get_result(), 15.0, 13) These two tests will test that the errors are handled correctly when the evaluate() function is called, when there are values missing from the input or the input is empty: def test_evaluate_failure_empty(self): with self.assertRaises(RuntimeError): calc = Calculator() calc.enter_operation('add') calc.evaluate() def test_evaluate_failure_missing_value(self): with self.assertRaises(RuntimeError): calc = Calculator() calc.enter_value(5) calc.enter_operation('add') calc.evaluate() That completes the test case for the Calculator class. Note that we have only used a small subset of the available test assertions over our two test classes. A full list of all the test assertions is available in the unittest module documentation at https://docs.python.org/2/library/unittest.html#test-cases. Once all the tests are written, they can be executed using the following command in the directory containing both the calculator and tests directories: python -m unittest discover -v Here, we have the unit test framework discover all the tests automatically (which is why following the expected naming convention of prefixing names with "test" is important). We also request verbose output with the -v parameter, which shows all the tests executed and their results, as shown in the following screenshot: Summary In this article, we looked at how the PDB tool can be used to find faults in Python code and applications. We also looked at using the logging module to have Python code output a log file during execution and how this can make debugging the failures easier, as well as automated unit testing for portions of the application. Resources for Article: Further resources on this subject: Basic Image Processing[article] IRemote Desktop to Your Pi from Everywhere[article] Scraping the Data [article]
Read more
  • 0
  • 0
  • 3339

article-image-raspberry-pi-led-blueprints
Packt
16 Sep 2015
5 min read
Save for later

Raspberry Pi LED Blueprints

Packt
16 Sep 2015
5 min read
Blinking LEDs is a popular application in the field of embedded development. In Raspberry Pi LED Blueprints by Agus Kurniawan, we are going to design, build, and test LED-based projects using the Raspberry Pi. To Implement real LED-based projects for Raspberry Pi, we need to learn how to interface various LED modules, such as LEDs, 7-segment, 4-digit 7-segment, and dot matrix to Raspberry Pi. We will get hands-on experience by exploring real-time LEDs with this project-based book. (For more resources related to this topic, see here.) Why Raspberry Pi? The Raspberry Pi was designed by the Raspberry Pi Foundation in the UK initially to help schoolkids learn basic computer science knowledge. The Raspberry Pi uses Linux as a basic programming language, and they attempt to come up with their own language that fits this technology better sometime in the future. Although Raspberry Pi is as small as the size of a credit card, it works like a normal computer at a relatively low price. A Raspberry Pi can easily control an LED, which is a simple actuator device that displays lighting. This book will provide you with the ability to control LEDs using Raspberry Pi. What this article covers? This article covers introduction of Raspberry Pi GPIO. In this, we will learn how to use different libraries to access Raspberry Pi GPIO. The step-by-step procedure to install it is also provided along with the Python command. Introducing Raspberry Pi GPIO General-purpose input/output (GPIO) is a generic pin on the Raspberry Pi, which can be used to interact with external devices, for instance, sensor and actuator devices. In general, you can see Raspberry Pi GPIO pinouts in the following figure: To access Raspberry Pi GPIO, we can use several GPIO libraries. If you are working with Python, Raspbian has already installed the RPi.GPIO library to access Raspberry Pi GPIO. You can read more about RPi.GPIO at https://pypi.python.org/pypi/RPi.GPIO. You can verify the RPi.GPIO library from a Python terminal by importing the RPi.GPIO module. If you don’t find this library on Python at runtime or get the error message ImportError: No module named RPi.GPIO, you can install it by compiling from the source code. For instance, if we want to install RPi.GPIO 0.5.11, type the following commands: wget https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-0.5.11.tar.gz tar -xvzf RPi.GPIO-0.5.11.tar.gz cd RPi.GPIO-0.5.11/ sudo python setup.py install To install and update through the apt command, your Raspberry Pi must be connected to the Internet. Another way to access Raspberry Pi GPIO is to use WiringPi. It is a library written in C for Raspberry Pi to access GPIO pins. You can read more about WiringPi at http://wiringpi.com/. To install WiringPi, you can type the following commands: sudo apt-get update sudo apt-get install git-core git clone git://git.drogon.net/wiringPi cd wiringPi sudo ./build Please make sure that your Pi network does not block the git protocol for git://git.dragon.net/wiringPi. You can browsed https://git.drogon.net/?p=wiringPi;a=summary for this code. The next step is to install the WiringPi interface for Python, so you can access Raspberry Pi GPIO from the Python program. Type the following commands: sudo apt-get install python-dev python-setuptools git clone https://github.com/Gadgetoid/WiringPi2-Python.git cd WiringPi2-Python sudo python setup.py install When finished, you can verify it by showing GPIO map from the Raspberry Pi board using the following gpio tool: gpio readall You should see the GPIO map from the Raspberry Pi board on the terminal. You can also see values in the wPi column, which will be used in the WirinPi program as GPIO value parameters. In this book, you can find more information about how to use it on the WiringPi library. What you need for this book? We are going to use Raspberry Pi 2 board Model B. To make Raspberry Pi work, we need OS that acts as a bridge between the hardware and the user. There are many OS options that you can use for Raspberry Pi. This book uses Raspbian for the OS platform for Raspberry Pi. To deploy Raspbian on Raspberry Pi 2 Model B, we need microSD card of at least 4 GB size. Who this book is written for? This book is for those who want to learn how to build Raspberry Pi projects using LEDs, 7-segment, 4-digit 7-segment, and dot matrix modules. You will also learn to implement those modules in real applications, including interfacing with wireless modules and the Android mobile app. However, you don't need to have any previous experience with the Raspberry Pi or Android platforms. Summary In this article, we learned different techniques to install Raspberry Pi GPIO. Read Raspberry Pi LED Blueprints to start designing and implementing several projects based on LEDs, such as 7-segments, 4-digit 7-segment, and dot matrix displays. Other related titles are: Raspberry Pi Blueprints Raspberry Pi Super Cluster Learning Raspberry Pi Raspberry Pi Robotic Projects Resources for Article: Further resources on this subject: Color and motion finding [article] Basic Image Processing [article] Develop a Digital Clock [article]
Read more
  • 0
  • 0
  • 2621

article-image-remote-desktop-your-pi-everywhere
Packt
16 Sep 2015
6 min read
Save for later

Remote Desktop to Your Pi from Everywhere

Packt
16 Sep 2015
6 min read
In this article by Gökhan Kurt, author of the book Raspberry Pi Android Projects, we will make a gentle introduction to both Pi and Android platforms to warm us up. Many users of the Pi face similar problems when they wish to administer it. You have to be near your Pi and connect a screen and a keyboard to it. We will solve this everyday problem by remotely connecting to our Pi desktop interface. The article covers the following topics: Installing necessary components in the Pi and Android Connecting the Pi and Android (For more resources related to this topic, see here.) Installing necessary components in the Pi and Android The following image shows you that the LXDE desktop manager comes with an initial setup and a few preinstalled programs: LXDE desktop management environment By clicking on the screen image on the tab bar located at top, you will be able to open a terminal screen that we will use to send commands to the Pi. The next step is to install a component called x11vnc. This is a VNC server for X, the window management component of Linux. Issue following command on the terminal: sudo apt-get install x11vnc This will download and install x11vnc to the Pi. We can even set a password to be used by VNC clients that will remote desktop to this Pi using the following command and provide a password to be used later on: x11vnc –storepasswd Next, we can get the x11vnc server running whenever the Pi is rebooted and the LXDE desktop manager starts. This can be done through the following steps: Go into the .config directory on the Pi user's home directory located at /home/pi:cd /home/pi/.config Make a subdirectory here named autostart:mkdir autostart Go into the autostart directory:cd autostart Start editing a file named x11vnc.desktop. As a terminal editor, I am using nano, which is the easiest one to use on the Pi for novice users, but there are more exciting alternatives, such as vi: nano x11vnc.desktop Add the following content into this file: [Desktop Entry] Encoding=UTF-8 Type=Application Name=X11VNC Comment= Exec=x11vnc -forever -usepw -display :0 -ultrafilexfer StartupNotify=false Terminal=false Hidden=false Save and exit using (Ctrl+X, Y, <Enter>) in order if you are using nano as the editor of your choice. Now you should reboot the Pi to get the server running using the following command: sudo reboot After rebooting, we can now find out what IP address our Pi has been given in the terminal window by issuing the ifconfig command. The IP address assigned to your Pi is to be found under the eth0 entry and is given after the inet addr keyword. Write this address down: Example output from ifconfig command The next step is to download a VNC client to your Android device.In this project, we will use a freely available client for Android, namely androidVNC or as it is named in the Play Store—VNC Viewer for Android by androidVNC team + antlersoft. The latest version in use at the writing of this book was 0.5.0. Note that in order to be able to connect your Android VNC client to the Pi, both the Pi and the Android device should be connected to the same network. Android through Wi-Fi and Pi through its Ethernet port. Connecting the Pi and Android Install and open androidVNC on your device. You will be presented with a first activity user interface asking for the details of the connection. Here, you should provide Nickname for the connection, Password you enter when you run the x11vnc –storepasswd command, and the IP Address of the Pi that you have found out using the ifconfig command. Initiate the connection by pressing the Connect button, and you should now be able to see the Pi desktop on your Android device. In androidVNC, you should be able to move the mouse pointer by clicking on the screen and under the options menu in the androidVNC app, you will find out how to send text and keys to the Pi with the help of Enter and Backspace. You may even find it convenient to connect to the Pi from another computer. I recommend using RealVNC for this purpose, which is available on Windows, Linux, and Mac OS. What if I want to use Wi-Fi on the Pi? In order to use a Wi-Fi dongle on the Pi, first of all, open the wpa-supplicant configuration file using the nano editor with the following command: sudo nano /etc/wpa_supplicant/wpa_supplicant.conf Add the following to the end of this file: network={ ssid="THE ID OF THE NETWORK YOU WANT TO CONNECT" psk="PASSWORD OF YOUR WIFI" } I assume that you have set up your wireless home network to use WPA-PSK as the authentication mechanism. If you have another mechanism, you should refer to the wpa_supplicant documentation. LXDE provides even better ways to connect to Wi-Fi networks through a GUI. It can be found on the upper-right corner of the desktop environment on the Pi. Connecting from everywhere Now, we have connected to the Pi from our device, which we need to connect to the same network as the Pi. However, most of us would like to connect to the Pi from around the world as well. To do this, first of all, we need to now the IP address of the home network assigned to us by our network provider. By going to http://whatismyipaddress.com URL, we can figure out what our home network's IP address is. The next step is to log in to our router and open up requests to the Pi from around the world. For this purpose, we will use a functionality found on most modern routers called port forwarding. Be aware of the risks contained in port forwarding. You are opening up access to your Pi from all around the world, even to malicious ones. I strongly recommend that you change the default password of the user pi before performing this step. You can change passwords using the passwd command. By logging onto a router's management portal and navigating to the Port Forwarding tab, we can open up requests to the Pi's internal network IP address, which we have figured out previously, and the default port of the VNC server, which is 5900. Now, we can provide our external IP address to androidVNC from anywhere around the world instead of an internal IP address that works only if we are on the same network as the Pi. Port forwarding settings on Netgear router administration page Refer to your router's user manual to see how to change the Port Forwarding settings. Most routers require you to connect through the Ethernet port in order to access the management portal instead of Wi-Fi. Summary In this article, we installed Raspbian, warmed up with the Pi, and connected the Pi using an Android device. Resources for Article:   Further resources on this subject: Raspberry Pi LED Blueprints [article] Color and motion finding [article] From Code to the Real World [article]
Read more
  • 0
  • 0
  • 1332
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-code-real-world
Packt
02 Sep 2015
22 min read
Save for later

From Code to the Real World

Packt
02 Sep 2015
22 min read
 In this article by Jorge R. Castro, author of Building a Home Security System with Arduino, you will learn to read a technical specification sheet, the ports on the Uno and how they work, the necessary elements for a proof of concept. Finally, we will extend the capabilities of our script in Python and rely on NFC technology. We will cover the following points: ProtoBoards and wiring Signals (digital and analog) Ports Datasheets (For more resources related to this topic, see here.) ProtoBoards and wiring There are many ways of working on and testing electrical components, one of the ways developers use is using ProtoBoards (also known as breadboards). Breadboards help eliminate the need to use soldering while testing out components and prototype circuit schematics, it lets us reuse components, enables rapid development, and allows us to correct mistakes and even improve the circuit design. It is a rectangle case composed of internally interconnected rows and columns; it is possible to couple several together. The holes on the face of the board are designed to in way that you can insert the pins of components to mount it. ProtoBoards may be the intermediate step before making our final PCB design, helping eliminate errors and reduce the associated cost. For more information visit http://en.wikipedia.org/wiki/Breadboard. We know have to know more about the wrong wiring techniques when using a breadboard. There are rules that have always been respected, and if not followed, it might lead to shorting out elements that can irreversibly damage our circuit.   A ProtoBoard and an Arduino Uno The ProtoBoard is shown in the preceding image; we can see there are mainly two areas - the vertical columns (lines that begin with the + and - polarity sign), and the central rows (with a coordinate system of letters and numbers). Both + and - usually connect to the electrical supply of our circuit and to the ground. It is advised not to connect components directly in the vertical columns, instead to use a wire to connect to the central rows of the breadboard. The central row number corresponds to a unique track. If we connected one of the leads of a resistor in the first pin of the first row then other lead should be connected to any other pin in another row, and not in the same row. There is an imaginary axis that divides the breadboard vertically in symmetrical halves, which implies that they are electrically independent. We will use this feature to use certain Integrated Circuits (IC), and they will be mounted astride the division.   Protoboard image obtained using Fritzing. Carefully note that in the preceding picture, the top half of the breadboard shows the components mounted incorrectly, while the lower half shows the components mounted the correct way. A chip is set correctly between the two areas, this usage is common for IC's. Fritzing is a tool that helps us create a quick circuit design of our project. Visit http://fritzing.org/download/ for more details on Fritzing. Analog and digital ports Now that we know about the correct usage of a breadboard, we now have another very important concept - ports. Our board will be composed of various inputs and outputs, the number of which varies with the kind of model we have. But what are ports? The Arduino UNO board has ports on its sides. They are connections that allow it to interact with sensors, actuators, and other devices (even with another Arduino board). The board also has ports that support digital and analog signals. The advantage is that these ports are bidirectional, and the programmers are able to define the behavior of these ports. In the following code, the first part shows that we set the status of the ports that we are going to use. This is the setup function: //CODE void setup(){ // Will run once, and use it to // "prepare" I/0 pins of Arduino pinMode(10, OUTPUT); // put the pin 10 as an output pinMode(11, INPUT); // put the pin 11 as an input } Lets take a look at what the digital and analog ports are on the Arduino UNO. Analog ports Analog signals are signals that continuously vary with time These can be explained as voltages that have continuously varying intermediate values. For example, it may vary from 2V to 3.3V to 3.0V, or 3.333V, which means that the voltages varied progressively with time, and are all different values from each other; the figures between the two values are infinite (theoretical value). This is an interesting property, and that is what we want. For example, if we want to measure the temperature of a room, the temperature measure takes values with decimals, need an analog signal. Otherwise, we will lose data, for example, in decimal values since we are not able to store infinite decimal numbers we perform a mathematical rounding (truncating the number). There is a process called discretization, and it is used to convert analog signals to digital. In reality, in the world of microcontrollers, the difference between two values is not infinite. The Arduino UNO's ports have a range of values between 0 and 1023 to describe an analog input signal. Certain ports, marked as PWM or by a ~, can create output signals that vary between values 0 and 255. Digital ports A digital signal consists of just two values - 0s and 1s. Many electronic devices internally have a range currently established, where voltage values from 3.5 to 5V are considered as a logic 1, and voltages from 0 to 2.5V are considered as a logic 0. To better understand this point, let's see an example of a button that triggers an alarm. The only useful cases for an alarm are when the button is pressed to ring the alarm and when it's not pressed; there are only two states observed. So unlike the case of the temperature sensor, where we can have a range of linear values, here only two values exist. Logically, we use these properties for different purposes. The Arduino IDE has some very illustrative examples. You can load them onto your board to study the concepts of analog and digital signals by navigating to File | Examples | Basic | Blink. Sensors There is a wide range of sensors, and without pretending to be an accurate guide of all possible sensors, we will try to establish some small differences. All physical properties or sets of them has an associated sensor, so we can measure the force (presence of people walking on the floor), movement (physical displacement even in the absence of light), smoke, gas, pictures (yes, the cameras also are sensors) noise (sound recording), antennas (radio waves, WiFi, and NFC), and an incredible list that would need a whole book to explain all its fantastic properties. It is also interesting to note that the sensors can also be specific and concrete; however, they only measure very accurate or nonspecific properties, being able to perceive a set of values but more accurately. If you go to an electronics store or a sales portal buy a humidity sensor (and generally any other electronic item), you will see a sensitive price range. In general, expensive sensors indicate that they are more reliable than their cheaper counterparts, the price also indicates the kinds of conditions that it can work in, and also the duration of operation. Expensive sensors can last more than the cheaper variants. When we started looking for a component, we looked to the datasheets of a particular component (the next point will explain what this document is), you will not be surprised to find two very similar models mentioned in the datasheets. It contains operating characteristics and different prices. Some components are professionally deployed (for instance in the technological and military sectors), while others are designed for general consumer electronics. Here, we will focus on those with average quality and foremost an economic price. We proceed with an example that will serve as a liaison with the following paragraph. To do this, we will use a temperature sensor (TMP-36) and an analog port on the Arduino UNO. The following image shows the circuit schematic:   Our design - designed using Fritzing The following is the code for the preceding circuit schematic: //CODE //########################### //Author : Jorge Reyes Castro //Arduino Home Security Book //########################### // A3 <- Input // Sensor TMP36 //########################### //Global Variable int outPut = 0; float outPutToVol = 0.0; float volToTemp = 0.0; void setup(){ Serial.begin(9600); // Start the SerialPort 9600 bauds } void loop(){ outPut = analogRead(A3); // Take the value from the A3 incoming port outPutToVol = 5.0 *(outPut/1024.0); // This is calculated with the values volToTemp = 100.0 *(outPutToVol - 0.5); // obtained from the datasheet Serial.print("_____________________n"); mprint("Output of the sensor ->", outPut); mprint("Conversion to voltage ->", outPutToVol); mprint("Conversion to temperature ->", volToTemp); delay(1000); // Wait 1 Sec. } // Create our print function // smarter than repeat the code and it will be reusable void mprint(char* text, double value){ // receives a pointer to the text and a numeric value of type double Serial.print(text); Serial.print("t"); // tabulation Serial.print(value); Serial.print("n"); // new line } Now, open a serial port from the IDE or just execute the previous Python script. We can see the output from the Arduino. Enter the following command to run the code as python script: $ python SerialPython.py The output will look like this: ____________________ Output of the sensor 145.00 Conversion to voltage 0.71 Conversion to temperature 20.80 _____________________ By using Python script, which is not simple, we managed to extract some data from a sensor after the signal is processed by the Arduino UNO. It is then extracted and read by the serial interface (script in Python) from the Arduino UNO. At this point, we will be able to do what we want with the retrieved data, we can store them in a database, represent them in a function, create a HTML document, and more. As you may have noticed we make a mathematical calculation. However, from where do we get this data? The answer is in the data sheet. Component datasheets Whenever we need to work with or handle an electrical component, we have to study their properties. For this, there are official documents, of variable length, in which the manufacturer carefully describes the characteristics of that component. First of all, we, have to identify that a component can either use the unique ID or model name that it was given when it was manufactured. TMP 36GZ We have very carefully studied the component surface and thus extracted the model. Then, using an Internet browser, we can quickly find the datasheet. Go to http://www.google.com and search for: TMP36GZ + datasheet, or visit http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Temp/TMP35_36_37.pdf to get the datasheet. Once you have the datasheet, you can see that it has various components which look similar, but with very different presentations (this can be crucial for a project, as an error in the choice of encapsulated (coating/presentation) can lead to a bitter surprise). Just as an example, if we confuse the presentation of our circuit, we might end up buying components used in cellphones, and those can hardly be soldered by a standard user as they smaller than your pinkie fingernail). Therefore, an important property to which you must pay attention is the coating/presentation of the components. In the initial pages of the datasheet you see that it shows you the physical aspects of the component. It then show you the technical characteristics, such as the working current, the output voltage, and other characteristics which we must study carefully in order to know whether they will be consistent with our setup. In this case, we are working with a range of input voltage (V) of between 2.7 V to 5.5 V is perfect. Our Arduino has an output of 5V. Furthermore, the temperature range seems appropriate. We do not wish to measure anything below 0V and 5V. Let's study the optimal behavior of the components in temperature ranges in more detail. The behavior of the components is stable only between the desired ranges. This is a very important aspect because although the measurement can be done at the ends supported by the sensor, the error will be much higher and enormously increases the deviation to small variations in ambient temperature. Therefore, always choose or build a circuit with components having the best performance as shown in the optimal region of the graph of the datasheet. Also, always respect and observe that the input voltages do not exceed the specified limit, otherwise it will be irreversibly damaged. To know more about ADC visit http://en.wikipedia.org/wiki/Analog-to-digital_converter. Once we have the temperature sensor, we have to extract the data you need. Therefore, we make a simple calculation supported in the datasheet. As we can see, we feed 5V to the sensor, and it return values between 0 and 1023. So, we use a simple formula that allows us to convert the values obtained in voltage (analog value): Voltage = (Value from the sensor) x (5/1024) The value 1024 is correct, as we have said that the data can range from 0 (including zero as a value) to 1023. This data can be strange to some, but in the world of computer and electronics, zero is seen as a very important value. Therefore, be careful when making calculations. Once we obtain a value in volts, we proceed to convert this measurement in a data in degrees. For this, by using the formula from the datasheet, we can perform the conversion quickly. We use a variable that can store data with decimal point (double or float), otherwise we will be truncating the result and losing valuable information (this may seem strange, but this bug very common). The formula for conversion is Cº = (Voltage -0.5) x 100.0. We now have all the data we need and there is a better implementation of this sensor, in which we can eliminate noise and disturbance from the data. You can dive deeper into these issues if desired. With the preceding explanation, it will not be difficult to achieve. Near Field Communication Near Field Communication (NFC) technology is based on the RFID technology. Basically, the principle consists of two devices fused onto one board, one acting as an antenna to transmit signals and the other that acts as a reader/reciever. It exchanges information using electromagnetic fields. They deal with small pieces of information. It is enough for us to make this extraordinary property almost magical. For more information on RFID and NFC, visit the following links: http://en.wikipedia.org/wiki/Near_field_communication http://en.wikipedia.org/wiki/Radio-frequency_identification Today, we find this technology in identification and access cards (a pioneering example is the Document ID used in countries like Spain), tickets for public transport, credit cards, and even mobile phones (with ability to make payment via NFC). For this project, we will use a popular module PN532 Adafruit RFID/NFC board. Feel free to use any module that suits your needs. I selected this for its value, price, and above all, for its chip. The popular PN532 is largely supported by the community, and there are vast number of publications, tools, and libraries that allow us to integrate it in many projects. For instance, you can use it in conjunction with an Arduino a Raspberry Pi, or directly with your computer (via a USB to serial adapter). Also, the PN532 board comes with a free Mifare 1k card, which we can use for our project. You can also buy tag cards or even key rings that house a small circuit inside, on which information is stored, even encrypted information. One of the benefits, besides the low price of a set of labels, is that we can block access to certain areas of information or even all the information. This allows us in maintaining our valuable data safely or avoid the cloned/duplicate of this security tag. There are a number of standards that allow us to classify the different types of existing cards, one of which is the Mifare 1K card (You can use the example presented here and make small changes to adapt it to other NFC cards). For more information on MIFARE cards, visit http://en.wikipedia.org/wiki/MIFARE. As the name suggests, this model can store up to 1KB (Kilobyte) information, and is of the EEPROM type (can be rewritten). Furthermore, it possesses a serial number unique to each card (this is very interesting because it is a perfect fingerprint that will allow us to distinguish between two cards with the same information). Internally, it is divided into 16 sectors (0-15), and is subdivided into 4 blocks (0-3) with at least 16 bytes of information. For each block, we can set a password that prevents reading your content if it does not pose. (At this point, we are not going to manipulate the key because the user can accidentally, encrypt a card, leaving it unusable). By default, all cards usually come with a default password (ffffffffffff). The reader should consult the link http://www.adafruit.com/product/789, to continue with the examples, or if you select another antenna, search the internet for the same features. The link also has tutorials to make the board compatible with other devices (Raspberry Pi), the datasheet, and the library can be downloaded from Github to use this module. We will have a look at this last point more closely later; just download the libraries for now and follow my steps. It is one of the best advantages of open hardware, that the designs can be changed and improved by anyone. Remember, when handling electrical components, we have to be careful and avoid electrostatic sources. As you have already seen, the module is inserted directly on the Arduino. If soldered pins do not engage directly above then you have to use Dupont male-female connectors to be accessible other unused ports. Once we have the mounted module, we will use the library that is used to control this device (top link) and install it. It is very important that you rename the library to download, eliminate possible blanks or the like. However, the import process may throw an error. Once we have this ready and have our Mifare 1k card close, let's look at a small example that will help us to better understand all this technology and get the UID (Unique Identifier) of our tag: // ########################### // Author : Jorge Reyes Castro // Arduino Home Security Book // ########################### #include <Wire.h> #include <Adafruit_NFCShield_I2C.h> // This is the Adafruit Library //MACROS #define IRQ (2) #define RESET (3) Adafruit_NFCShield_I2C nfc(IRQ, RESET); //Prepare NFC MODULE //SETUP void setup(void){ Serial.begin(115200); //Open Serial Port Serial.print("###### Serial Port Ready ######n"); nfc.begin(); //Start NFC nfc.SAMConfig(); if(!Serial){ //If the serial port don´ work wait delay(500); } } //LOOP void loop(void) { uint8_t success; uint8_t uid[] = { 0, 0, 0, 0}; //Buffer to save the read value //uint8_t ok[] = { X, X, X, X }; //Put your serial Number. * 1 uint8_t uidLength; success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); // READ // If TAG PRESENT if (success) { Serial.println("Found cardn"); Serial.print(" UID Value: t"); nfc.PrintHex(uid, uidLength); //Convert Bytes to Hex. int n = 0; Serial.print("Your Serial Number: t"); // This function show the real value // 4 position runs extracting data while (n < 4){ // Copy and remenber to use in the next example * 1 Serial.print(uid[n]); Serial.print("t"); n++; } Serial.println(""); } delay(1500); //wait 1'5 sec } Now open a serial port from the IDE or just execute the previous Python script. We can see the output from the Arduino. Enter the following command to run the Python code: $ python SerialPython.py The output will look like this: ###### Serial Port Ready ###### Found card UID Value: 0xED 0x05 0xED 0x9A Your Serial Number: 237 5 237 154 So we have our own identification number, but what are those letters that appear above our number? Well, it is hexadecimal, another widely used way to represent numbers and information in the computer. It represents a small set of characters and more numbers in decimal notation than we usually use. (Remember our card with little space. We use hexadecimal to be more useful to save memory). An example is the number 15, we need two characters in tenth, while in decimal just one character is needed f (0xf, this is how the hexadecimal code, preceded by 0x, this is a thing to remember as this would be of great help later on). Open a console and the Python screen. Run the following code to obtain hexadecimal numbers, and will see transformation to decimal (you can replace them with the values previously put in the code): For more information about numbering systems, see http://en.wikipedia.org/wiki/Hexadecimal. $ python >>> 0xED 237 >>> 0x05 5 >>> 0x9A 154 You can see that they are same numbers.   RFID/NFC module and tag Once we are already familiar with the use of this technology, we proceed to increase the difficultly and create our little access control. Be sure to record the serial number of your access card (in decimal). We will make this little montage focus on the use of NFC cards, no authentication key. As mentioned earlier, there is a variant of this exercise and I suggest that the reader complete this on their part, thus increasing the robustness of our assembly. In addition, we add a LED and buzzer to help us improve the usability. Access control The objective is simple: we just have to let people in who have a specific card with a specific serial number. If you want to use encrypted keys, you can change the ID of an encrypted message inside the card with a key known only to the creator of the card. When a successful identification occurs, a green flash lead us to report that someone has had authorized access to the system. In addition, the user is notified of the access through a pleasant sound, for example, will invite you to push the door to open it. Otherwise, an alarm is sounded repeatedly, alerting us of the offense and activating an alert command center (a red flash that is repeated and consistent, which captures the attention of the watchman.) Feel free to add more elements. The diagram shall be as follows:   Our scheme – Image obtained using Fritzing The following is a much clearer representation of the preceding wiring diagram as it avoids the part of the antenna for easy reading:   Our design - Image obtained using Fritzing Once we clear the way to take our design, you can begin to connect all elements and then create our code for the project. The following is the code for the NFC access: //########################### //Author : Jorge Reyes Castro //Arduino Home Security Book //########################### #include <Wire.h> #include <Adafruit_NFCShield_I2C.h> // this is the Adafruit Library //MACROS #define IRQ (2) #define RESET (3) Adafruit_NFCShield_I2C nfc(IRQ, RESET); //Prepare NFC MODULE void setup(void) { pinMode(5, OUTPUT); // PIEZO pinMode(9, OUTPUT); // LED RED pinMode(10, OUTPUT); // LED GREEN okHAL(); Serial.begin(115200); //Open Serial Port Serial.print("###### Serial Port Ready ######n"); nfc.begin(); //Start NFC nfc.SAMConfig(); if(!Serial){ // If the Serial Port don't work wait delay(500); } } void loop(void) { uint8_t success; uint8_t uid[] = { 0, 0, 0, 0}; //Buffer to storage the ID from the read tag uint8_t ok[] = { 237, 5, 237, 154}; //Put your serial Number. uint8_t uidLength; success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); //READ if (success) { okHAL(); // Sound "OK" Serial.println("Found cardn"); Serial.print(" UID Value: t"); nfc.PrintHex(uid, uidLength); // The Value from the UID in HEX int n = 0; Serial.print("Your Serial Number: t"); // The Value from the UID in DEC while (n < 4){ Serial.print(uid[n]); Serial.print("t"); n++; } Serial.println(""); Serial.println(" Wait..n"); // Verification int m = 0, l = 0; while (m < 5){ if(uid[m] == ok[l]){ // Compare the elements one by one from the obtained UID card that was stored previously by us. } else if(m == 4){ Serial.println("###### Authorized ######n"); // ALL OK authOk(); okHAL(); } else{ Serial.println("###### Unauthorized ######n"); // NOT EQUALS ALARM !!! authError(); errorHAL(); m = 6; } m++; l++; } } delay(1500); } //create a function that allows us to quickly create sounds // alarm ( "time to wait" in ms, "tone/power") void alarm(unsigned char wait, unsigned char power ){ analogWrite(5, power); delay(wait); analogWrite(5, 0); } // HAL OK void okHAL(){ alarm(200, 250); alarm(100, 50); alarm(300, 250); } // HAL ERROR void errorHAL(){ int n = 0 ; while(n< 3){ alarm(200, 50); alarm(100, 250); alarm(300, 50); n++; } } // These functions activated led when we called. // (Look at the code of the upper part where they are used) // RED - FAST void authError(){ int n = 0 ; while(n< 20){ digitalWrite(9, HIGH); delay(500); digitalWrite(9, LOW); delay(500); n++; } } // GREEN - SLOW void authOk(){ int n = 0 ; while(n< 5){ digitalWrite(10, HIGH); delay(2000); digitalWrite(10, LOW); delay(500); n++; } } // This code can be reduced to increase efficiency and speed of execution, // but has been created with didactic purposes and therefore increased readability Once you have the copy, compile it, and throw it on your board. Ensure that our creation now has a voice, whenever we start communicating or when someone tries to authenticate. In addition, we have added two simple LEDs that give us much information about our design. Finally, we have our whole system, perhaps it will be time to improve our Python script and try the serial port settings, creating a red window or alarm sound on the computer that is receiving the data. It is the turn of reader to assimilate all of the concepts seen in this day and modify them to delve deeper and deeper into the wonderful world of programming. Summary This has been an intense article, full of new elements. We learned to handle technical documentation fluently, covered the different type of signals and their main differences, found the perfect component for our needs, and finally applied it to a real project, without forgetting the NFC. This has just been introduced, laying the foundation for the reader to be able to modify and study it deeper it in the future. Resources for Article: Further resources on this subject: Getting Started with Arduino[article] Arduino Development[article] The Arduino Mobile Robot [article]
Read more
  • 0
  • 0
  • 2880

article-image-getting-started-arduino
Packt
20 Aug 2015
12 min read
Save for later

Getting Started with Arduino

Packt
20 Aug 2015
12 min read
Hello there! If you are reading this article by Adith Jagadish Boloor, the author of the book Arduino By Example, it means that you've taken your first step to make fascinating projects using Arduinos. This article will teach you how to set up an Arduino and write your first Arduino code. You'll be in good hands whilst you learn some of the basics aspects of coding using the Arduino platform, which will allow you to build almost anything from robots, home automation systems, touch interfaces, sensory systems, and so on. Firstly, you will learn how to install the powerful Arduino software, then set that up, followed by hooking up your Arduino board and, after making sure that everything is fine and well, you will write your first code! Once you are comfortable with that, we will modify the code to make it do something more, which is often what Arduino coders do. We do not just create completely new programs but often we build on what has been done before, to make it better and more suited to our objectives. The contents of this article are divided into the following topics: Prerequisites Setting up Hello World Summary (For more resources related to this topic, see here.) Prerequisites Well, you can't jump onto a horse without putting on a saddle first, can you? This section will cover what components you need to start coding on an Arduino. These can be purchased from your favorite electrical hobby store or simply ordered online. Materials needed 1x Arduino compatible board such as an Arduino UNO 1x USB cable A to B 2x LEDs 2x 330Ω resistors A mini breadboard 5x male-to-male jumper wires Note The UNO can be substituted for any other Arduino board (Mega, Leonardo and so on) for most of the projects. These boards have their own extra features. For example, the Mega has almost double the number of I/O (input/output) pins for added functionality. The Leonardo has a feature which enables it to control the keyboard and mouse of your computer. Setting up This topic involves downloading the Arduino software, installing the drivers, hooking up the Arduino, and understanding the IDE menus. Downloading and installing the software Arduino is open source-oriented. This means all the software is free to use non-commercially. Go to http://arduino.cc/en/Main/Software and download the latest version for your specific operating system. If you are using a Mac, make sure you choose the right Java version, and similarly on Linux, download the 32 or 64 bit version according to your computer. Arduino download page Windows Once you have downloaded the setup file, run it. If it asks for administrator privileges, allow it. Install it in its default location (C:Program FilesArduino or C:Program Files (x86)Arduino). Create a new folder in this location and rename it My Codes or something where you can conveniently store all your programs. Mac OS X Once the ZIP file has finished downloading, double-click to expand it. Copy the Arduino application to the Applications folder. You won't have to install additional drivers to make the Arduino work since we will be using only the Arduino UNO and MEGA. You're all set. If you didn't get anything to work, go to https://www.arduino.cc/en/guide/macOSX. Linux (Ubuntu 12.04 and above) Once you have downloaded the latest version of Arduino from the above link, install the compiler and the library packages using the following command: sudo apt-get update && sudo apt-get install arduino arduino-core If you are using a different version of Linux, this official Arduino walkthrough at http://playground.arduino.cc/Learning/Linux will help you out. Connecting the Arduino It is time to hook up the Arduino board. Plug in the respective USB terminals to the USB cable and the tiny LEDs on the Arduino should begin to flash. Arduino UNO plugged in If the LEDs didn't turn on, ensure that the USB port on your computer is functioning and make sure the cable isn't faulty. If it still does not light up, there is something wrong with your board and you should get it checked. Windows The computer will begin to install the drivers for the Arduino by itself. If it does not succeed, do the following: Open Device Manager Click on Ports (COM & LPT) Right-click on Unknown Device and select Properties Click install driver and choose browse files on the computer Choose the drivers folder in the previously installed Arduino folder The computer should say that your Arduino UNO (USB) has been successfully installed on COM port (xx). Here xx refers to a single or double digit number. If this message didn't pop up, go back to the Device Manager and check if it has been installed under COM ports. Arduino UNO COM port Remember the (COMxx) port that the Arduino UNO was installed on. Mac OS X If you are using Mac OS, a dialog box will tell you that a new network interface has been detected. Click Network Preferences and select Apply. Even though the Arduino board may show up as Not Configured, it should be working perfectly. Linux You are ready to go. The serial ports for Mac OS and Linux will be obtained once the Arduino software has been launched. The Arduino IDE The Arduino software, commonly referred to as the Arduino IDE (integrated development environment). The IDE for Windows, Mac OS and Linux is almost identical. Now let's look at some of the highlights of this software. Arduino IDE This is the window that you will see when you first start up the IDE. The tick/check mark verifies that your code's syntax is correct. The arrow pointing right is the button that uploads the code to the board and checks if the code has been changed since the last upload or verification. The magnifying glass is the Serial Monitor. This is used to input text or output debugging statements or sensor values. Examples of Arduino Every Arduino programmer starts by using one of these examples. Even after mastering Arduino, one would still return here to find examples to use. Arduino tools The screenshot shows the tools that are available in the Arduino IDE. The Board option opens up all the different boards that the software supports. Hello World The easiest way to start working with Arduinos begins here. You'll learn how to output print statements. The Arduino uses a Serial Monitor for displaying information such as print statements, sensor data and the like. This is a very powerful tool for debugging long codes. Now for your first code! Writing a simple print statement Open up the Arduino IDE and copy the following code into a new sketch. void setup() { Serial.begin(9600); Serial.println("Hello World!"); } void loop() { } Open Tools | Board and choose Arduino UNO, as shown in the following screenshot: Open Tools | Port and choose the appropriate port (remember the previous COM xx number? select that), as shown in the following screenshot. For Mac and Linux users, once you have connected the Arduino board, going to Tools | Serial Port will give you a list of ports. The Arduino is typically something like /dev/tty.usbmodem12345 where 12345 will be different. Selecting port Finally, hit the upload button. If everything is fine, the LEDs on the Arduino should start flickering as the code is uploaded to the Arduino. The code will then have uploaded to the Arduino. To see what you have accomplished, click on the Serial Monitor button on the right side and switch the baud rate on the Serial Monitor window to 9600. You should see your message Hello World! waiting for you there. LED blink That wasn't too bad but it isn't cool enough. This article will enlighten you, literally. Open up a new sketch. Go to File | Examples | Basics | Blink. Blink example Before we upload the code, we need to make sure of one more thing. Remember the LED that we spoke about in the prerequisites? Let’s learn a bit about it before plugging it in. LED basics We will make use of it now. Plug in the LED such that the longer leg goes into pin 13 and the shorter leg goes into the GND pin as in the following images: LED blink setup (Fritzing) This diagram is made using software called Fritzing. This software will be used in future projects to make it cleaner to see and easier to understand as compared to a photograph with all the wires running around. Fritzing is opensource software which you can learn more about at www.fritzing.org. Arduino LED setup Upload the code. Your LED will start blinking, as shown in the following image. Lit up LED Isn't it just fascinating? You just programmed your first hardware. There's no stopping you now. Let's see what the code does and what happens when you change it. This is the blink example code that you just used. /* Blink Turns on an LED on for one second, then off for one second, repeatedly. This example code is in the public domain. */ //Pin 13 has an LED connected on most Arduino boards. //give it a name: int led = 13; //the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } //the loop routine runs over and over again forever: void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } We have three major sections in this code. int led = 13; This line simply stores the numerical PIN value onto a variable called led. void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } This is the setup function. Here is where you tell the Arduino what is connected on each used pin. In this case, we tell the Arduino that there is an output device (LED) on pin 13. void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } This is the loop function. It tells the Arduino to keep repeating whatever is inside it in a sequence. The digitalWrite command is like a switch that can be turned ON (HIGH) or OFF (LOW). The delay(1000) function simply makes the Arduino wait for a second before heading to the next line. If you wanted to add another LED, you'd need some additional tools and some changes to the code. This is the setup that you want to create. Connecting two LEDs to an Arduino If this is your first time using a breadboard, take some time to make sure all the connections are in the right place. The colors of the wires don't matter. However, GND is denoted using a black wire and VCC/5V/PWR is denoted with a red wire. The two resistors, each connected in series (acting like a connecting wire itself) with the LEDs limit the current flowing to the LEDs, making sure they don't blow up. As before, create a new sketch and paste in the following code: /* Double Blink Turns on and off two LEDs alternatively for one second each repeatedly. This example code is in the public domain. */ int led1 = 12; int led2 = 13; void setup() { // initialize the digital pins as an output. pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); // turn off LEDs before loop begins digitalWrite(led1, LOW); // turn the LED off (LOW is the voltage level) digitalWrite(led2, LOW); // turn the LED off (LOW is the voltage level) } //the loop routine runs over and over again forever: void loop() { digitalWrite(led1, HIGH); // turn the LED on (HIGH is the voltage level) digitalWrite(led2, LOW); // turn the LED off (LOW is the voltage level) delay(1000); // wait for a second digitalWrite(led1, LOW); // turn the LED off (LOW is the voltage level) digitalWrite(led2, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second } Once again, make sure the connections are made properly, especially the positive LEDs (longer to OUTPUT PIN) and the negative (shorter to GND) terminals. Save the code into DoubleBlink.ino. Now, if you make any changes to it, you can always retrieve it. Upload the code. 3… 2… 1… And there you have it, an alternating LED blink cycle created purely with the Arduino. You can try changing the delay to see its effects. For the sake of completeness, I would like to mention that you could take this mini-project further by using a battery to power the system and decorate your desk/room/house. Summary You have now completed the basic introduction to the world of Arduino. In short, you have successfully set up your Arduino and have written your first code. You also learned how to modify the existing code to create something new, making it more suitable for your specific needs. This methodology will be applied repeatedly while programming, because almost all the code available is open source and it saves time and energy. Resources for Article: Further resources on this subject: Central Air and Heating Thermostat [article] Christmas Light Sequencer [article] Webcam and Video Wizardry [article]
Read more
  • 0
  • 0
  • 2480

article-image-integrating-muzzley
Packt
10 Aug 2015
12 min read
Save for later

Integrating with Muzzley

Packt
10 Aug 2015
12 min read
In this article by Miguel de Sousa, author of the book Internet of Things with Intel Galileo, we will cover the following topics: Wiring the circuit The Muzzley IoT ecosystem Creating a Muzzley app Lighting up the entrance door (For more resources related to this topic, see here.) One identified issue regarding IoT is that there will be lots of connected devices and each one speaks its own language, not sharing the same protocols with other devices. This leads to an increasing number of apps to control each of those devices. Every time you purchase connected products, you'll be required to have the exclusive product app, and, in the near future, where it is predicted that more devices will be connected to the Internet than people, this is indeed a problem, which is known as the basket of remotes. Many solutions have been appearing for this problem. Some of them focus on creating common communication standards between the devices or even creating their own protocol such as the Intel Common Connectivity Framework (CCF). A different approach consists in predicting the device's interactions, where collected data is used to predict and trigger actions on the specific devices. An example using this approach is Muzzley. It not only supports a common way to speak with the devices, but also learns from the users' interaction, allowing them to control all their devices from a common app, and on collecting usage data, it can predict users' actions and even make different devices work together. In this article, we will start by understanding what Muzzley is and how we can integrate with it. We will then do some development to allow you to control your own building's entrance door. For this purpose, we will use Galileo as a bridge to communicate with a relay and the Muzzley cloud, allowing you to control the door from a common mobile app and from anywhere as long as there is Internet access. Wiring the circuit In this article, we'll be using a real home AC inter-communicator with a building entrance door unlock button and this will require you to do some homework. This integration will require you to open your inter-communicator and adjust the inner circuit, so be aware that there are always risks of damaging it. If you don't want to use a real inter-communicator, you can replace it by an LED or even by the buzzer module. If you want to use a real device, you can use a DC inter-communicator, but in this guide, we'll only be explaining how to do the wiring using an AC inter-communicator. The first thing you have to do is to take a look at the device manual and check whether it works with AC current, and the voltage it requires. If you can't locate your product manual, search for it online. In this article, we'll be using the solid state relay. This relay accepts a voltage range from 24 V up to 380 V AC, and your inter-communicator should also work in this voltage range. You'll also need some electrical wires and electrical wires junctions: Wire junctions and the solid state relay This equipment will be used to adapt the door unlocking circuit to allow it to be controlled from the Galileo board using a relay. The main idea is to use a relay to close the door opener circuit, resulting in the door being unlocked. This can be accomplished by joining the inter-communicator switch wires with the relay wires. Use some wire and wire junctions to do it, as displayed in the following image: Wiring the circuit The building/house AC circuit is represented in yellow, and S1 and S2 represent the inter-communicator switch (button). On pressing the button, we will also be closing this circuit, and the door will be unlocked. This way, the lock can be controlled both ways, using the original button and the relay. Before starting to wire the circuit, make sure that the inter-communicator circuit is powered off. If you can't switch it off, you can always turn off your house electrical board for a couple of minutes. Make sure that it is powered off by pressing the unlock button and trying to open the door. If you are not sure of what you must do or don't feel comfortable doing it, ask for help from someone more experienced. Open your inter-communicator, locate the switch, and perform the changes displayed in the preceding image (you may have to do some soldering). The Intel Galileo board will then activate the relay using pin 13, where you should wire it to the relay's connector number 3, and the Galileo's ground (GND) should be connected to the relay's connector number 4. Beware that not all the inter-communicator circuits work the same way and although we try to provide a general way to do it, there're always the risk of damaging your device or being electrocuted. Do it at your own risk. Power on your inter-communicator circuit and check whether you can open the door by pressing the unlock door button. If you prefer not using the inter-communicator with the relay, you can always replace it with a buzzer or an LED to simulate the door opening. Also, since the relay is connected to Galileo's pin 13, with the same relay code, you'll have visual feedback from the Galileo's onboard LED. The Muzzley IoT ecosystem Muzzley is an Internet of Things ecosystem that is composed of connected devices, mobile apps, and cloud-based services. Devices can be integrated with Muzzley through the device cloud or the device itself: It offers device control, a rules system, and a machine learning system that predicts and suggests actions, based on the device usage. The mobile app is available for Android, iOS, and Windows phone. It can pack all your Internet-connected devices in to a single common app, allowing them to be controlled together, and to work with other devices that are available in real-world stores or even other homemade connected devices, like the one we will create in this article. Muzzley is known for being one of the first generation platforms with the ability to predict a users' actions by learning from the user's interaction with their own devices. Human behavior is mostly unpredictable, but for convenience, people end up creating routines in their daily lives. The interaction with home devices is an example where human behavior can be observed and learned by an automated system. Muzzley tries to take advantage of these behaviors by identifying the user's recurrent routines and making suggestions that could accelerate and simplify the interaction with the mobile app and devices. Devices that don't know of each others' existence get connected through the user behavior and may create synergies among themselves. When the user starts using the Muzzley app, the interaction is observed by a profiler agent that tries to acquire a behavioral network of the linked cause-effect events. When the frequency of these network associations becomes important enough, the profiler agent emits a suggestion for the user to act upon. For instance, if every time a user arrives home, he switches on the house lights, check the thermostat, and adjust the air conditioner accordingly, the profiler agent will emit a set of suggestions based on this. The cause of the suggestion is identified and shortcuts are offered for the effect-associated action. For instance, the user could receive in the Muzzley app the following suggestions: "You are arriving at a known location. Every time you arrive here, you switch on the «Entrance bulb». Would you like to do it now?"; or "You are arriving at a known location. The thermostat «Living room» says that the temperature is at 15 degrees Celsius. Would you like to set your «Living room» air conditioner to 21 degrees Celsius?" When it comes to security and privacy, Muzzley takes it seriously and all the collected data is used exclusively to analyze behaviors to help make your life easier. This is the system where we will be integrating our door unlocker. Creating a Muzzley app The first step is to own a Muzzley developer account. If you don't have one yet, you can obtain one by visiting https://muzzley.com/developers, clicking on the Sign up button, and submitting the displayed form. To create an app, click on the top menu option Apps and then Create app. Name your App Galileo Lock and if you want to, add a description to your project. As soon as you click on Submit, you'll see two buttons displayed, allowing you to select the integration type: Muzzley allows you to integrate through the product manufacturer cloud or directly with a device. In this example, we will be integrating directly with the device. To do so, click on Device to Cloud integration. Fill in the provider name as you wish and pick two image URLs to be used as the profile (for example, http://hub.packtpub.com/wp-content/uploads/2015/08/Commercial1.jpg) and channel (for example, http://hub.packtpub.com/wp-content/uploads/2015/08/lock.png) images. We can select one of two available ways to add our device: it can be done using UPnP discovery or by inserting a custom serial number. Pick the device discovery option Serial number and ignore the fields Interface UUID and Email Access List; we will come back for them later. Save your changes by pressing the Save changes button. Lighting up the entrance door Now that we can unlock our door from anywhere using the mobile phone with an Internet connection, a nice thing to have is the entrance lights turn on when you open the building door using your Muzzley app. To do this, you can use the Muzzley workers to define rules to perform an action when the door is unlocked using the mobile app. To do this, you'll need to own one of the Muzzley-enabled smart bulbs such as Philips Hue, WeMo LED Lighting, Milight, Easybulb, or LIFX. You can find all the enabled devices in the app profiles selection list: If you don't have those specific lighting devices but have another type of connected device, search the available list to see whether it is supported. If it is, you can use that instead. Add your bulb channel to your account. You should now find it listed in your channels under the category Lighting. If you click on it, you'll be able to control the lights. To activate the trigger option in the lock profile we created previously, go to the Muzzley website and head back to the Profile Spec app, located inside App Details. Expand the property lock status by clicking on the arrow sign in the property #1 - Lock Status section and then expand the controlInterfaces section. Create a new control interface by clicking on the +controlInterface button. In the new controlInterface #1 section, we'll need to define the possible choices of label-values for this property when setting a rule. Feel free to insert an id, and in the control interface option, select the text-picker option. In the config field, we'll need to specify each of the available options, setting the display label and the real value that will be published. Insert the following JSON object: {"options":[{"value":"true","label":"Lock"}, {"value":"false","label":"Unlock"}]}. Now we need to create a trigger. In the profile spec, expand the trigger section. Create a new trigger by clicking on the +trigger button. Inside the newly created section, select the equals condition. Create an input by clicking on +input, insert the ID value, insert the ID of the control interface you have just created in the controlInterfaceId text field. Finally, add the [{"source":"selection.value","target":"data.value"}].path to map the data. Open your mobile app and click on the workers icon. Clicking on Create Worker will display the worker creation menu to you. Here, you'll be able to select a channel component property as a trigger to some other channel component property: Select the lock and select the Lock Status is equal to Unlock trigger. Save it and select the action button. In here, select the smart bulb you own and select the Status On option: After saving this rule, give it a try and use your mobile phone to unlock the door. The smart bulb should then turn on. With this, you can configure many things in your home even before you arrive there. In this specific scenario, we used our door locker as a trigger to accomplish an action on a lightbulb. If you want, you can do the opposite and open the door when a lightbulb lights up a specific color for instance. To do it, similar to how you configured your device trigger, you just have to set up the action options in your device profile page. Summary Everyday objects that surround us are being transformed into information ecosystems and the way we interact with them is slowly changing. Although IoT is growing up fast, it is nowadays in an early stage, and many issues must be solved in order to make it successfully scalable. By 2020, it is estimated that there will be more than 25 billion devices connected to the Internet. This fast growth without security regulations and deep security studies are leading to major concerns regarding the two biggest IoT challenges—security and privacy. Devices in our home that are remotely controllable or even personal data information getting into the wrong hands could be the recipe for a disaster. In this article you have learned the basic steps in wiring the circuit of your Galileo board, creating a Muzzley app, and lighting up the entrance door of your building through your Muzzley app, by using Intel Galileo board as a bridge to communicate with Muzzley cloud. Resources for Article: Further resources on this subject: Getting Started with Intel Galileo [article] Getting the current weather forecast [article] Controlling DC motors using a shield [article]
Read more
  • 0
  • 0
  • 1960

article-image-programmable-dc-motor-controller-lcd
Packt
23 Jul 2015
23 min read
Save for later

Programmable DC Motor Controller with an LCD

Packt
23 Jul 2015
23 min read
In this article by Don Wilcher author of the book Arduino Electronics Blueprints, we will see how a programmable logic controller (PLC) is used to operate various electronic and electromechanical devices that are wired to I/O wiring modules. The PLC receives signals from sensors, transducers, and electromechanical switches that are wired to its input wiring module and processes the electrical data by using a microcontroller. The embedded software that is stored in the microcontroller's memory can control external devices, such as electromechanical relays, motors (the AC and DC types), solenoids, and visual displays that are wired to its output wiring module. The PLC programmer programs the industrial computer by using a special programming language known as ladder logic. The PLC ladder logic is a graphical programming language that uses computer instruction symbols for automation and controls to operate robots, industrial machines, and conveyor systems. The PLC, along with the ladder logic software, is very expensive. However, with its off-the-shelf electronic components, Arduino can be used as an alternate mini industrial controller for Maker type robotics and machine control projects. In this article, we will see how Arduino can operate as a mini PLC that is capable of controlling a small electric DC motor with a simple two-step programming procedure. Details regarding how one can interface a transistor DC motor with a discrete digital logic circuit to an Arduino and write the control cursor selection code will be provided as well. This article will also provide the build instructions for a programmable motor controller. The LCD will provide the programming directions that are needed to operate an electric motor. The parts that are required to build a programmable motor controller are shown in the next section. Parts list The following list comprises the parts that are required to build the programmable motor controller: Arduino Uno: one unit 1 kilo ohm resistor (brown, black, red, gold): three units A 10-ohm resistor (brown, black, black, gold): one unit A 10-kilo ohm resistor (brown, black, orange, gold): one unit A 100-ohm resistor (brown, black, brown, gold): one unit A 0.01 µF capacitor: one unit An LCD module: one unit A 74LS08 Quad AND Logic Gate Integrated Circuit: one unit A 1N4001 general purpose silicon diode: one unit A DC electric motor (3 V rated): one unit Single-pole double-throw (SPDT) electric switches: two units 1.5 V batteries: two units 3 V battery holder: one unit A breadboard Wires A programmable motor controller block diagram The block diagram of the programmable DC motor controller with a Liquid Crystal Display (LCD) can be imagined as a remote control box with two slide switches and an LCD, as shown in following diagram:   The Remote Control Box provides the control signals to operate a DC motor. This box is not able to provide the right amount of electrical current to directly operate the DC motor. Therefore, a transistor motor driver circuit is needed. This circuit has sufficient current gain hfe to operate a small DC motor. A typical hfe value of 100 is sufficient for the operation of a DC motor. The Enable slide switch is used to set the remote control box to the ready mode. The Program switch allows the DC motor to be set to an ON or OFF operating condition by using a simple selection sequence. The LCD displays the ON or OFF selection prompts that help you operate the DC motor. The remote control box diagram is shown in the next image. The idea behind the concept diagram is to illustrate how a simple programmable motor controller can be built by using basic electrical and electronic components. The Arduino is placed inside the remote control box and wired to the Enable/Program switches and the LCD. External wires are attached to the transistor motor driver, DC motor, and Arduino. The block diagram of the programmable motor controller is an engineering tool that is used to convey a complete product design by using simple graphics. The block diagram also allows ease in planning the breadboard to prototype and test the programmable motor controller in a maker workshop or a laboratory bench. A final observation regarding the block diagram of the programmable motor controller is that the basic computer convention of inputs is on the left, the processor is located in the middle, and the outputs are placed on the right-hand side of the design layout. As shown, the SPDT switches are on the left-hand side, Arduino is located in the middle, and the transistor motor driver with the DC Motor is on the right-hand side of the block diagram. The LCD is shown towards the right of the block diagram because it is an output device. The LCD allows visual selection between the ON/OFF operations of the DC motor by using Program switch. This left-to-right design method allows ease in building the programmable motor controller as well as troubleshooting errors during the testing phase of the project. The block diagram for a programmable motor controller is as follows:   Building the programmable motor controller The block diagram of the programmable motor controller has more circuits than the block diagram of the sound effects machine. As discussed previously, there are a variety of ways to build the (prototype) electronic devices. For instance, they can be built on a Printed Circuit Board (PCB) or an experimenter's/prototype board. The construction base that was used to build this device was a solderless breadboard, which is shown in the next image. The placement of the electronic parts, as shown in the image, are not restricted to the solderless breadboard layout. Rather, it should be used as a guideline. Another method of placing the parts onto the solderless breadboard is to use the block diagram that was shown earlier. This method of arranging the parts that was illustrated in the block diagram allows ease in testing each subcircuit separately. For example, the Program/Enable SPDT switches' subcircuits can be tested by using a DC voltmeter. Placing a DC voltmeter across the Program switch and 1 kilo ohm resistor and toggling switch several times will show a voltage swing between 0 V and +5 V. The same testing method can be carried out on the Enable switch as well. The transistor motor driver circuit is tested by placing a +5 V signal on the base of the 2N3904 NPN transistor. When you apply +5 V to the transistor's base, the DC motor turns on. The final test for the programmable DC motor controller is to adjust the contrast control (10 kilo ohm) to see whether the individual pixels are visible on the LCD. This electrical testing method, which is used to check the programmable DC motor controller is functioning properly, will minimize the electronic I/O wiring errors. Also, the electrical testing phase ensures that all the I/O circuits of the electronics used in the circuit are working properly, thereby allowing the maker to focus on coding the software. Following is the wiring diagram of programmable DC motor controller with the LCD using a solderless breadboard:   As shown in the wiring diagram, the electrical components that are used to build the programmable DC motor controller with the LCD circuit are placed on the solderless breadboard for ease in wiring the Arduino, LCD, and the DC motor. The transistor shown in the preceding image is a 2N3904 NPN device with a pin-out arrangement consisting of an emitter, a base, and a collector respectively. If the transistor pins are wired incorrectly, the DC motor will not turn on. The LCD module is used as a visual display, which allows operating selection of the DC motor. The program slide switch turns the DC motor ON or OFF. Although most of the 16-pin LCD modules have the same electrical pin-out names, consult the manufacturer's datasheet of the available device in hand. There is also a 10 kilo ohm potentiometer to control the LCD's contrast. On wiring the LCD to the Arduino, supply power to the microcontroller board by using the USB cable that is connected to a desktop PC or a notebook. Adjust the 10 kilo ohm potentiometer until a row of square pixels are visible on the LCD. The Program slide switch is used to switch between the ON or OFF operating mode of the DC motor, which is shown on the LCD. The 74LS08 Quad AND gate is a 14-pin Integrated Circuit (IC) that is used to enable the DC motor or get the electronic controller ready to operate the DC motor. Therefore, the Program slide switch must be in the ON position for the electronic controller to operate properly. The 1N4001 diode is used to protect the 2N3904 NPN transistor from peak currents that are stored by the DC motor's winding while turning on the DC motor. When the DC motor is turned off, the 1N4001 diode will direct the peak current to flow through the DC motor's windings, thereby suppressing the transient electrical noise and preventing damage to the transistor. Therefore, it's important to include this electronic component into the design, as shown in the wiring diagram, to prevent electrical damage to the transistor. Besides the wiring diagram, the circuit's schematic diagram will aid in building the programmable motor controller device. Let's build it! In order to build the programmable DC motor controller, follow the following steps: Wire the programmable DC motor controller with the LCD circuit on a solderless breadboard, as shown in the previous image as well as the circuit's schematic diagram that is shown in the next image. Upload the software of the programmable motor controller to the Arduino by using the sketch shown next. Close both the Program and Enables switches. The motor will spin. When you open the Enable switch, the motor stops. The LCD message tells you how one can set the Program switch for an ON and OFF motor control. The Program switch allows you to select between the ON and OFF motor control functions. With the Program switch closed, toggling the Enable switch will turn the motor ON and OFF. Opening the Program switch will prevent the motor from turning on. The next few sections will explain additional details on the I/O interfacing of discrete digital logic circuits and a small DC motor that can be connected to the Arduino. A sketch is a unit of code that is uploaded to and run on an Arduino board. /* * programmable DC motor controller w/LCD allows the user to select ON and OFF operations using a slide switch. To * enable the selected operation another slide switch is used to initiate the selected choice. * Program Switch wired to pin 6. * Output select wired to pin 7. * LCD used to display programming choices (ON or OFF). * created 24 Dec 2012 * by Don Wilcher */ // include the library code: #include <LiquidCrystal.h>   // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   // constants won't change. They're used here to // set pin numbers: const int ProgramPin = 6;     // pin number for PROGRAM input control signal const int OUTPin = 7;     // pin number for OUTPUT control signal   // variable will change: int ProgramStatus = 0; // variable for reading Program input status     void setup() { // initialize the following pin as an output: pinMode(OUTPin, OUTPUT);   // initialize the following pin as an input: pinMode(ProgramPin, INPUT);   // set up the LCD's number of rows and columns: lcd.begin(16, 2);   // set cursor for messages andprint Program select messages on the LCD. lcd.setCursor(0,0); lcd.print( "1. ON"); lcd.setCursor(0, 1); lcd.print ( "2. OFF");   }   void loop(){ // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program select choice is 1.ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);   } else{      digitalWrite(OUTPin,LOW); } } The schematic diagram of the circuit that is used to build the programmable DC motor controller and upload the sketch to the Arduino is shown in the following image:   Interfacing a discrete digital logic circuit with Arduino The Enable switch, along with the Arduino, is wired to a discrete digital Integrated Circuit (IC) that is used to turn on the transistor motor driver. The discrete digital IC used to turn on the transistor motor driver is a 74LS08 Quad AND gate. The AND gate provides a high output signal when both the inputs are equal to +5 V. The Arduino provides a high input signal to the 74LS08 AND gate IC based on the following line of code:    digitalWrite(OUTPin, HIGH); The OUTPin constant name is declared in the Arduino sketch by using the following declaration statement: const int OUTPin = 7;     // pin number for OUTPUT control signal The Enable switch is also used to provide a +5V input signal to the 74LS08 AND gate IC. The Enable switch circuit schematic diagram is as follows:   Both the inputs must have the value of logic 1 (+5 V) to make an AND logic gate produce a binary 1 output. In the following section, the truth table of an AND logic gate is given. The table shows all the input combinations along with the resultant outputs. Also, along with the truth table, the symbol for an AND logic gate is provided. A truth table is a graphical analysis tool that is used to test digital logic gates and circuits. By setting the inputs of a digital logic gate to binary 1 (5 V) or binary 0 (0 V), the truth table will show the binary output values of 1 or 0 of the logic gate. The truth table of an AND logic gate is given as follows:   Another tool that is used to demonstrate the operation of the digital logic gates is the Boolean Logic expression. The Boolean Logic expression for an AND logic gate is as follows:   A Boolean Logic expression is an algebraic equation that defines the operation of a logic gate. As shown for the AND gate, the Boolean Logic expression circuit's output, which is denoted by C, is only equal to the product of A and B inputs. Another way of observing the operation of the AND gate, based on its Boolean Logic Expression, is by setting the value of the circuit's inputs to 1. Its output has the same binary bit value. The truth table graphically shows the results of the Boolean Logic expression of the AND gate. A common application of the AND logic gate is the Enable circuit. The output of the Enable circuit will only be turned on when both the inputs are on. When the Enable circuit is wired correctly on the solderless breadboard and is working properly, the transistor driver circuit will turn on the DC motor that is wired to it. The operation of the programmable DC motor controller's Enable circuit is shown in the following truth table:   The basic computer circuit that makes the decision to operate the DC motor is the AND logic gate. The previous schematic diagram of the Enable Switch circuit shows the electrical wiring to the specific pins of the 74LS08 IC, but internally, the AND logic gate is the main circuit component for the programmable DC motor controller's Enable function. Following is the diagram of 74LS08 AND Logic Gate IC:   To test the Enable circuit function of the programmable DC motor controller, the Program switch is required. The schematic diagram of the circuit that is required to wire the Program Switch to the Arduino is shown in the following diagram. The Program and Enable switch circuits are identical to each other because two 5 V input signals are required for the AND logic gate to work properly. The Arduino sketch that was used to test the Enable function of the programmable DC motor is shown in the following diagram:   The program for the discrete digital logic circuit with an Arduino is as follows: // constants won't change. They're used here to // set pin numbers: const int ProgramPin = 6;   // pin number for PROGRAM input control signal const int OUTPin = 7;     // pin number for OUTPUT control signal   // variable will change: int ProgramStatus = 0;       // variable for reading Program input status   void setup() { // initialize the following pin as an output: pinMode(OUTPin, OUTPUT);   // initialize the following pin as an input: pinMode(ProgramPin, INPUT); }   void loop(){   // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program switch is ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);   } else{      digitalWrite(OUTPin,LOW);   } } Connect a DC voltmeter's positive test lead to the D7 pin of the Arduino. Upload the preceding sketch to the Arduino and close the Program and Enable switches. The DC voltmeter should approximately read +5 V. Opening the Enable switch will display 0 V on the DC voltmeter. The other input conditions of the Enable circuit can be tested by using the truth table of the AND Gate that was shown earlier. Although the DC motor is not wired directly to the Arduino, by using the circuit schematic diagram shown previously, the truth table will ensure that the programmed Enable function is working properly. Next, connect the DC voltmeter to the pin 3 of the 74LS08 IC and repeat the truth table test again. The pin 3 of the 74LS08 IC will only be ON when both the Program and Enable switches are closed. If the AND logic gate IC pin generates wrong data on the DC voltmeter when compared to the truth table, recheck the wiring of the circuit carefully and properly correct the mistakes in the electrical connections. When the corrections are made, repeat the truth table test for proper operation of the Enable circuit. Interfacing a small DC motor with a digital logic gate The 74LS08 AND Logic Gate IC provides an electrical interface between reading the Enable switch trigger and the Arduino's digital output pin, pin D7. With both the input pins (1 and 2) of the 74LS08 AND logic gate set to binary 1, the small 14-pin IC's output pin 3 will be High. Although the logic gate IC's output pin has a +5 V source present, it will not be able to turn a small DC motor. The 74LS08 logic gate's sourcing current is not able to directly operate a small DC motor. To solve this problem, a transistor is used to operate a small DC motor. The transistor has sufficient current gain hfe to operate the DC motor. The DC motor will be turned on when the transistor is biased properly. Biasing is a technique pertaining to the transistor circuit, where providing an input voltage that is greater than the base-emitter junction voltage (VBE) turns on the semiconductor device. A typical value for VBE is 700 mV. Once the transistor is biased properly, any electrical device that is wired between the collector and +VCC (collector supply voltage) will be turned on. An electrical current will flow from +VCC through the DC motor's windings and the collector-emitter is grounded. The circuit that is used to operate a small DC motor is called a Transistor motor driver, and is shown in the following diagram:   The Arduino code that is responsible for the operation of the transistor motor driver circuit is as follows: void loop(){   // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program switch is ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);   } else{      digitalWrite(OUTPin,LOW);   } } Although the transistor motor driver circuit was not directly wired to the Arduino, the output pin of the microcontroller prototyping platform indirectly controls the electromechanical part by using the 74LS08 AND logic gate IC. A tip to keep in mind when using the transistors is to ensure that the semiconductor device can handle the current requirements of the DC motor that is wired to it. If the DC motor requires more than 500 mA of current, consider using a power Metal Oxide Semiconductor Field Effect Transistor (MOSFET) instead. A power MOSFET device such as IRF521 (N-Channel) and 520 (N-Channel) can handle up to 1 A of current quite easily, and generates very little heat. The low heat dissipation of the power MOSFET (PMOSFET) makes it more ideal for the operation of high-current motors than a general-purpose transistor. A simple PMOSFET DC motor driver circuit can easily be built with a handful of components and tested on a solderless breadboard, as shown in the following image. The circuit schematic for the solderless breadboard diagram is shown after the breadboard image as well. Sliding the Single Pole-Double Throw (SPDT)switch in one position biases the PMOSFET and turns on the DC motor. Sliding the switch in the opposite direction turns off the PMOSFET and the DC motor.   Once this circuit has been tested on the solderless breadboard, replace the 2N3904 transistor in the programmable DC Motor controller project with the power-efficient PMOSFET component mentioned earlier. As an additional reference, the schematic diagram of the transistor relay driver circuit is as follows:   A sketch of the LCD selection cursor The LCD provides a simple user interface for the operation of a DC motor that is wired to the Arduino-based programmable DC motor controller. The LCD provides the two basic motor operations of ON and OFF. Although the LCD shows the two DC motor operation options, the display doesn't provide any visual indication of selection when using the Program switch. An enhancement feature of the LCD is that it shows which DC motor operation has been selected by adding a selection symbol. The LCD selection feature provides a visual indicator of the DC motor operation that was selected by the Program switch. This selection feature can be easily implemented for the programmable DC motor controller LCD by adding a > symbol to the Arduino sketch. After uploading the original sketch from the Let's build it section of this article, the LCD will display two DC motor operation options, as shown in the following image:   The enhancement concept sketch of the new LCD selection feature is as follows:   The selection symbol points to the DC motor operation that is based on the Program switch position. (For reference, see the schematic diagram of the programmable DC motor controller circuit.) The partially programmable DC motor controller program sketch that comes without an LCD selection feature Comparing the original LCD DC motor operation selection with the new sketch, the differences with regard to the programming features are as follows: void loop(){   // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program switch is ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);   } else{    digitalWrite(OUTPin,LOW);   } } The partially programmable DC motor controller program sketch with an LCD selection feature This code feature will provide a selection cursor on the LCD to choose the programmable DC motor controller operation mode: // set cursor for messages and print Program select messages on the LCD. lcd.setCursor(0,0); lcd.print( ">1.Closed(ON)"); lcd.setCursor(0, 1); lcd.print ( ">2.Open(OFF)");     void loop(){   // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program select choice is 1.ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);      lcd.setCursor(0,0);      lcd.print( ">1.Closed(ON)");      lcd.setCursor(0,1);      lcd.print ( " 2.Open(OFF) ");   } else{      digitalWrite(OUTPin,LOW);      lcd.setCursor(0,1);      lcd.print ( ">2.Open(OFF)");      lcd.setCursor(0,0);      lcd.print( " 1.Closed(ON) ");   } } The most obvious difference between the two partial Arduino sketches is that the LCD selection feature has several lines of code as compared to the original one. As the slide position of the Program switch changes, the LCD's selection symbol instantly moves to the correct operating mode. Although the DC motor can be observed directly, the LCD confirms the operating mode of the electromechanical device. The complete LCD selection sketch is shown in the following section. As a design-related challenge, try displaying an actual arrow for the DC motor operating mode on the LCD. As illustrated in the sketch, an arrow can be built by using the keyboard symbols or the American Standard Code for Information Interchange (ASCII) code. /* * programmable DC motor controller w/LCD allows the user to select ON and OFF operations using a slide switch. To * enable the selected operation another slide switch is used to initiate the selected choice. * Program Switch wired to pin 6. * Output select wired to pin 7. * LCD used to display programming choices (ON or OFF) with selection arrow. * created 28 Dec 2012 * by Don Wilcher */ // include the library code: #include <LiquidCrystal.h>   // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   // constants won't change. They're used here to // set pin numbers: const int ProgramPin = 6;     // pin number for PROGRAM input control signal const int OUTPin = 7;       // pin number for OUTPUT control signal     // variable will change: int ProgramStatus = 0;       // variable for reading Program input status     void setup() { // initialize the following pin as an output: pinMode(OUTPin, OUTPUT);   // initialize the following pin as an input: pinMode(ProgramPin, INPUT);   // set up the LCD's number of rows and columns: lcd.begin(16, 2);   // set cursor for messages andprint Program select messages on the LCD. lcd.setCursor(0,0); lcd.print( ">1.Closed(ON)"); lcd.setCursor(0, 1); lcd.print ( ">2.Open(OFF)");   }   void loop(){   // read the status of the Program Switch value: ProgramStatus = digitalRead(ProgramPin);   // check if Program select choice is 1.ON. if(ProgramStatus == HIGH) {    digitalWrite(OUTPin, HIGH);      lcd.setCursor(0,0);      lcd.print( ">1.Closed(ON)");      lcd.setCursor(0,1);      lcd.print ( " 2.Open(OFF) ");   } else{      digitalWrite(OUTPin,LOW);      lcd.setCursor(0,1);      lcd.print ( ">2.Open(OFF)");      lcd.setCursor(0,0);      lcd.print( " 1.Closed(ON) ");   } } Congratulations on building your programmable motor controller device! Summary In this article, a programmable motor controller was built using an Arduino, AND gate, and transistor motor driver. The fundamentals of digital electronics, which include the concepts of Boolean logic expressions and truth tables were explained in the article. The AND gate is not able to control a small DC motor because of the high amount of current that is needed to operate it properly. PMOSFET (IRF521) is able to operate a small DC motor because of its high current sourcing capability. The circuit that is used to wire a transistor to a small DC motor is called a transistor DC motor driver. The DC motor can be turned on or off by using the LCD cursor selection feature of the programmable DC motor controller. Resources for Article: Further resources on this subject: Arduino Development [article] Prototyping Arduino Projects using Python [article] The Arduino Mobile Robot [article]
Read more
  • 0
  • 0
  • 7693
article-image-whats-bitbake-all-about
Packt
08 Jul 2015
7 min read
Save for later

What's BitBake All About?

Packt
08 Jul 2015
7 min read
In this article by H M Irfan Sadiq, the author of the book Using Yocto Project with BeagleBone Black, we will move one step ahead by detailing different aspects of the basic engine behind Yocto Project, and other similar projects. This engine is BitBake. Covering all the various aspects of BitBake in one article is not possible; it will require a complete book. We will familiarize you as much as possible with this tool. We will cover the following topics in this article: Legacy tools and BitBake Execution of BitBake (For more resources related to this topic, see here.) Legacy tools and BitBake This discussion does not intend to invoke any religious row between other alternatives and BitBake. Every step in the evolution has its own importance, which cannot be denied, and so do other available tools. BitBake was developed keeping in mind the Embedded Linux Development domain. So, it tried to solve the problems faced in this core area, and in my opinion, it addresses these in the best way till date. You might get the same output using other tools, such as Buildroot, but the flexibility and ease provided by BitBake in this domain is second to none. The major difference is in addressing the problem. Legacy tools are developed considering packages in mind, but BitBake evolved to solve the problems faced during the creation of BSPs, or embedded distributions. Let's go through the challenges faced in this specific domain and understand how BitBake helps us face them. Cross-compilation BitBake takes care of cross compilation. You do not have to worry about it for each package you are building. You can use the same set of packages and build for different platforms seamlessly. Resolving inter-package dependencies This is the real pain of resolving dependencies of packages on each other and fulfilling them. In this case, we need to specify the different dependency types available, and BitBake takes care of them for us. We can handle both build and runtime dependencies. Variety of target distribution BitBake supports a variety of target distribution creations. We can define a full new distribution of our own, by choosing package management, image types, and other artifacts to fulfill our requirements. Coupling to build system BitBake is not very dependent on the build system we use to build our target images. We don't use libraries and tools installed on the system; we build their native versions and use them instead. This way, we are not dependent on the build system's root filesystem. Variety of build systems distros Since BitBake is very loosely coupled to the build system's distribution type, it's very easy to use on various distributions. Variety of architecture We have to support different architectures. We don't have to modify our recipes for each package. We can write our recipes so that features, parameters, and flags are picked up conditionally. Exploit parallelism For the simplest projects, we have to build images and do more than a thousand tasks. These tasks require us to use the full power available to us, whether they are computational or related to memory. BitBake's architecture supports us in this regard, using its scheduler to run as many tasks in parallel as it can, or as we configure. Also, when we say task, it should not be confused with package, but it is a part of package. A package can contain many tasks, (fetch, compile, configure, package, populate_sysroot, and so on), and all these can run in parallel. Easy to use, extend, and collaborate Keeping and relying on metadata keeps things simple and configurable. Almost nothing is hard coded. Thus, we can configure things according to our requirements. Also, BitBake provides us with a mechanism to reuse things that are already developed. We can keep our metadata structured, so that it gets applied/extended conditionally. You will learn these tricks when we will explore layers. BitBake execution To get us to a successful package or image, BitBake performs some steps that we need to go through to get an understanding of the workflow. In certain cases, some of these steps can be avoided; but we are not discussing such cases, considering them as corner cases. For details on these, we should refer to the BitBake user manual. Parsing metadata When we invoke the BitBake command to build our image, the first thing it does is parse our base configuration metadata. This metadata consists of build_bb/conf/bblayers.conf, multiple layer/conf/layer.conf, and poky/meta/conf/bitbake.conf. This data can be of the following types: Configuration data Class data Recipes Key variables BBFILES and BBPATH, which are constructed from the layer.conf file. Thus, the constructed BBPATH variable is used to locate configuration files under conf/ and class files under class/ directories. The BBFILES variable is used to find recipe files (.bb and .bbappend). bblayers.conf is used to set these variables. Next, the bitbake.conf file is parsed. If there is no bblayers.conf file, it is assumed that the user has set BBFILES and BBPATH directly in the environment. After having dealt with configuration files, class files inclusion and parsing are taken care of. These class files are specified using the INHERIT variable. Next, BitBake will use the BBFILES variable to construct a list of recipes to parse, along with any append files. Thus, after parsing, recipe values for various variables are stored into datastore. After the completion of a recipe parsing BitBake has: A list of tasks that the recipe has defined A set of data consisting of keys and values Dependency information of the tasks Preparing tasklist BitBake starts looking through the PROVIDES set in recipe files. The PROVIDES set defaults to the recipe name, and we can define multiple values to it. We can have multiple recipes providing a similar package. This task is accomplished by setting PROVIDES in the recipes. While actually making such recipes part of the build, we have to define PRREFERED_PROVIDER_foo so that our specific recipe foo can be used. We can do this in multiple locations. In the case of kernels, we use it in the manchin.conf file. BitBake iterates through the list of targets it has to build and resolves them, along with their dependencies. If PRREFERED_PROVIDER is not set and multiple versions of a package exist, BitBake will choose the highest version. Each target/recipe has multiple tasks, such as fetch, unpack, configure, and compile. BitBake considers each of these tasks as independent units to exploit parallelism in a multicore environment. Although these tasks are executed sequentially for a single package/recipe, for multiple packages, they are run in parallel. We may be compiling one recipe, configuring the second, and unpacking the third in parallel. Or, may be at the start, eight packages are all fetching their sources. For now, we should know the dependencies between tasks that are defined using DEPENDS and RDEPENDS. In DEPENDS, we provide the dependencies that our package needs to build successfully. So, BitBake takes care of building these dependencies before our package is built. RDEPENDS are the dependencies that are required for our package to execute/run successfully on the target system. So, BitBake takes care of providing these dependencies on the target's root filesystem. Executing tasks Tasks can be defined using the shell syntax or Python. In the case of shell tasks, a shell script is created under a temporary directory as run.do_taskname.pid and then, it is executed. The generated shell script contains all the exported variables and the shell functions, with all the variables expanded. Output from the task is saved in the same directory with log.do_taskname.pid. In the case of errors, BitBake shows the full path to this logfile. This is helpful for debugging. Summary In this article, you learned the goals and problem areas that BitBake has considered, thus making itself a unique option for Embedded Linux Development. You also learned how BitBake actually works. Resources for Article: Further resources on this subject: Learning BeagleBone [article] Baking Bits with Yocto Project [article] The BSP Layer [article]
Read more
  • 0
  • 0
  • 2063

article-image-installation-and-setup
Packt
07 Jul 2015
15 min read
Save for later

Installation and Setup

Packt
07 Jul 2015
15 min read
The Banana Pi is a single-board computer, which enables you to build your own individual and versatile system. In fact, it is a complete computer, including all the required elements such as a processor, memory, network, and other interfaces, which we are going to explore. It provides enough power to run even relatively complex applications suitably. In this article by, Ryad El-Dajani, author of the book, Banana Pi Cookbook, we are going to get to know the Banana Pi device. The available distributions are mentioned, as well as how to download and install these distributions. We will also examine Android in contrast to our upcoming Linux adventure. (For more resources related to this topic, see here.) Thus, you are going to transform your little piece of hardware into a functional, running computer with a working operating system. You will master the whole process of doing the required task from connecting the cables, choosing an operating system, writing the image to an SD card, and successfully booting up and shutting down your device for the first time. Banana Pi Overview In the following picture, you see a Banana Pi on the left-hand side and a Banana Pro on the right-hand side: As you can see, there are some small differences that we need to notice. The Banana Pi provides a dedicated composite video output besides the HDMI output. However, with the Banana Pro, you can connect your display via composite video output using a four-pole composite audio/video cable on the jack. In contrast to the Banana Pi, which has 26 pin headers, the Banana Pro provides 40 pins. Also the pins for the UART port interface are located below the GPIO headers on the Pi, while they are located besides the network interface on the Pro. The other two important differences are not clearly visible on the previous picture. The operating system for your device comes in the form of image files that need to be written (burned) to an SD card. The Banana Pi uses normal SD cards while the Banana Pro will only accept Micro SD cards. Moreover, the Banana Pro provides a Wi-Fi interface already on board. Therefore, you are also able to connect the Banana Pro to your wireless network, while the Pi would require an external wireless USB device. Besides the mentioned differences, the devices are very similar. You will find the following hardware components and interfaces on your device. On the back side, you will find: A20 ARM Cortex-A7 dual core central processing unit (CPU) ARM Mali400 MP2 graphics processing unit (GPU) 1 gigabyte of DDR3 memory (that is shared with the GPU) On the front side, you will find: Ethernet network interface adapter Two USB 2.0 ports A 5V micro USB power with DC in and a micro USB OTG port A SATA 2.0 port and SATA power output Various display outputs [HDMI, LVDS, and composite (integrated into jack on the Pro)] A CSI camera input connector An infrared (IR) receiver A microphone Various hardware buttons on board (power key, reset key, and UBoot key) Various LEDs (red for power status, blue for Ethernet status, and green for user defined) As you can see, you have a lot of opportunities for letting your device interact with various external components. Operating systems for the Banana Pi The Banana Pi is capable of running any operating system that supports the ARM Cortex-A7 architecture. There are several operating systems precompiled, so you are able to write the operating system to an SD card and boot your system flawlessly. Currently, there are the following operating systems provided officially by LeMaker, the manufacturer of the Banana Pi. Android Android is a well-known operating system for mobile phones, but it is also runnable on various other devices such as smart watches, cars, and, of course, single-board computers such as the Banana Pi. The main advantage of running Android on a single-board computer is its convenience. Anybody who uses an Android-based smartphone will recognize the graphical user interface (GUI) and may have less initial hurdles. Also, setting up a media center might be easier to do on Android than on a Linux-based system. However, there are also a few disadvantages, as you are limited to software that is provided by an Android store such as Google Play. As most apps are optimized for mobile use at the moment, you will not find a lot of usable software for your Banana Pi running Android, except some Games and Multimedia applications. Moreover, you are required to use special Windows software called PhoenixCard to be able to prepare an Android SD card. In this article, we are going to ignore the installing of Android. For further information, please see Installing the Android OS image (LeMaker Wiki) at http://wiki.lemaker.org/BananaPro/Pi:SD_card_installation. Linux Most of the Linux users never realize that they are actually using Linux when operating their phones, appliances, routers, and many more products, as most of its magic happens in the background. We are going to dig into this adventure to discover its possibilities when running on our Banana Pi device. The following Linux-based operating systems—so-called distributions—are used by the majority of the Banana Pi user base and are supported officially by the manufacturer: Lubuntu: This is a lightweight distribution based on the well-known Ubuntu using the LXDE desktop, which is principally a good choice, if you are a Windows user. Raspbian: This is a distribution based on Debian, which was initially produced for the Raspberry Pi (hence the name). As a lot of Raspberry Pi owners are running Raspbian on their devices while also experimenting with the Banana Pi, LeMaker ported the original Raspbian distribution to the Banana Pi. Raspbian also comes with an LXDE desktop by default. Bananian: This too is a Debian-based Linux distribution optimized exclusively for the Banana Pi and its siblings. All of the aforementioned distributions are based on the well-known distribution, Debian. Besides the huge user base, all Debian-based distributions use the same package manager Apt (Advanced Packaging Tool) to search for and install new software, and all are similar to use. There are still more distributions that are officially supported by LeMaker, such as Berryboot, LeMedia, OpenSUSE, Fedora, Gentoo, Scratch, ArchLinux, Open MediaVault, and OpenWrt. All of them have their pros and cons or their specific use cases. If you are an experienced Linux user, you may choose your preferred distribution from the mentioned list, as most of the recipes are similar to, or even equally usable on, most of the Linux-based operating systems. Moreover, the Banana Pi community publishes various customized Linux distributions for the Banana Pi regularly. The possible advantages of a customized distribution may include enabled and optimized hardware acceleration capabilities, supportive helper scripts, fully equipped desktop environments, and much more. However, when deciding to use a customized distribution, there is no official support by LeMaker and you have to contact the publisher in case you encounter bugs, or need help. You can also check the customized Arch Linux image that author have built (http://blog.eldajani.net/banana-pi-arch-linux-customized-distribution/) for the Banana Pi and Banana Pro, including several useful applications. Downloading an operating system for the Banana Pi The following two recipes will explain how to set up the SD card with the desired operating system and how to get the Banana Pi up and running for the first time. This recipe is a predecessor. Besides the device itself, you will need at least a source for energy, which is usually a USB power supply and an SD card to boot your Banana Pi. Also, a network cable and connection is highly recommended to be able to interact with your Banana Pi from another computer via a remote shell using the application. You might also want to actually see something on a display. Then, you will need to connect your Banana Pi via HDMI, composite, or LVDS to an external screen. It is recommended that you use an HDMI Version 1.4 cable since lower versions can possibly cause issues. Besides inputting data using a remote shell, you can directly connect an USB keyboard and mouse to your Banana Pi via the USB ports. After completing the required tasks in the upcoming recipes, you will be able to boot your Banana Pi. Getting ready The following components are required for this recipe: Banana Pi SD card (minimum class 4; class 10 is recommended) USB power supply (5V 2A recommended) A computer with an SD card reader/writer (to write the image to the SD card) Furthermore, you are going to need an Internet connection to download a Linux distribution or Android. A few optional but highly recommended components are: Connection to a display (via HDMI or composite) Network connection via Ethernet USB keyboard and mouse You can acquire these items from various retailers. All items shown in the previous two pictures were bought from an online retailer that is known for originally selling books. However, the Banana Pi and the other products can be acquired from a large number of retailers. It is recommended to get a USB power supply with 2000mA (2A) output. How to do it… To download an operating system for Banana Pi, follow these steps: Download an image of your desired operating system. We are going to download Android and Raspbian from the official LeMaker image files website: http://www.lemaker.org/resources/9-38/image_files.html. The following screenshot shows the LeMaker website where you can download the official images: If you are clicking on one of the mirrors (such as Google Drive, Dropbox, and so on), you will be redirected to the equivalent file-hosting service. From there, you are actually able to download the archive file. Once your archive containing the image is downloaded, you are ready to unpack the downloaded archive, which we will do in the upcoming recipes. Setting up the SD card on Windows This recipe will explain how to set up the SD card using a Windows operating system. How to do it… In the upcoming steps, we will unpack the archive containing the operating system image for the Banana Pi and write the image to the SD card: Open the downloaded archive with 7-Zip. The following screenshot shows the 7-Zip application opening a compressed .tgz archive: Unpack the archive to a directory until you get a file with the file extension .img. If it is .tgz or .tar.gz file, you will need to unpack the archive twice Create a backup of the contents of the SD card as everything on the SD card is going to be erased unrecoverablely. Open SD Formatter (https://www.sdcard.org/downloads/formatter_4/) and check the disk letter (E: in the following screenshot). Choose Option to open the Option Setting window and choose: FORMAT TYPE: FULL (Erase) FORMAT SIZE ADJUSTMENT: ON When everything is configured correctly, check again to see whether you are using the correct disk and click Format to start the formatting process. Writing a Linux distribution image to the SD card on Windows The following steps explain how to write a Linux-based distribution to the SD card on Windows: Format the SD card using SD Formatter, which we covered in the previous section. Open the Win32 Disk Imager (http://sourceforge.net/projects/win32diskimager/). Choose the image file by clicking on the directory button. Check, whether you are going to write to the correct disk and then click on Write. Once the burning process is done, you are ready to insert the freshly prepared SD card containing your Linux operating system into the Banana Pi and boot it up for the first time. Booting up and shutting down the Banana Pi This recipe will explain how to boot up and shut down the Banana Pi. As the Banana Pi is a real computer, these tasks are as equally important as tasks on your desktop computer. The booting process starts the Linux kernel and several important services. The shutting down stops them accordingly and does not power off the Banana Pi until all data is synchronized with the SD card or external components correctly. How to do it… We are going to boot up and shut down the Banana Pi. Booting up Do the following steps to boot up your Banana Pi: Attach the Ethernet cable to your local network. Connect your Banana Pi to a display. Plug in an USB keyboard and mouse. Insert the SD card to your device. Power your Banana Pi by plugging in the USB power cable. The next screenshot shows the desktop of Raspbian after a successful boot: Shutting down Linux To shut down your Linux-based distribution, you either use the shutdown command or do it via the desktop environment (in case of Raspbian, it is called LXDE). For the latter method, these are the steps: Click on the LXDE icon in the lower-left corner. Click on Logout. Click on Shutdown in the upcoming window. To shut down your operating system via the shell, type in the following command: $ sudo shutdown -h now Connecting via SSH on Windows using PuTTY The following recipe shows you how to connect to your Banana Pi remotely using an open source application called PuTTY. Getting ready For this recipe, you will need the following ingredients: A booted up Linux operating system on your Banana Pi connected to your local network The PuTTY application on your Windows PC that is also connected to your local area network How to do it… To connect to your Banana Pi via SSH on Windows, perform the following: Run putty.exe. You will see the PuTTY Configuration dialog. Enter the IP address of the Banana Pi and leave the Port as number 22 as. Click on the Open button. A new terminal will appear, attempting a connection to the Banana Pi. When connecting to the Banana Pi for the first time, you will see a PuTTY security alert. The following screenshot shows the PuTTY Security Alert window: Trust the connection by clicking on Yes. You will be requested to enter the login credentials. Use the default username bananapi and password bananapi. When you are done, you should be welcomed by the shell of your Banana Pi. The following screenshot shows the shell of your Banana Pi accessed via SSH using PuTTY on Windows: To quit your SSH session, execute the command exit or press Ctrl + D. Searching, installing, and removing the software Once you have your decent operating system on the Banana Pi, sooner or later you are going to require a new software. As most software for Linux systems is published as open source, you can obtain the source code and compile it for yourself. One alternative is to use a package manager. A lot of software is precompiled and provided as installable packages by the so-called repositories. In case of Debian-based distributions (for example, Raspbian, Bananian, and Lubuntu), the package manager that uses these repositories is called Advanced Packaging Tool (Apt). The two most important tools for our requirements will be apt-get and apt-cache. In this recipe, we will cover the searching, the installing, and removing of software using the Apt utilities. Getting ready The following ingredients are required for this recipe. A booted Debian-based operating system on your Banana Pi An Internet connection How to do it… We will separate this recipe into searching for, installing and removing of packages. Searching for packages In the upcoming example, we will search for a solitaire game: Connect to your Banana Pi remotely or open a terminal on the desktop. Type the following command into the shell: $ apt-cache search solitaire You will get a list of packages that contain the string solitaire in their package name or description. Each line represents a package and shows the package name and description separated by a dash (-). Now we have obtained a list of solitaire games: The preceding screenshot shows the output after searching for packages containing the string solitaire using the apt-cache command. Installing a package We are going to install a package by using its package name. From the previous received list, we select the package ace-of-penguins. Type the following command into the shell: $ sudo apt-get install ace-of-penguins If asked to type the password for sudo, enter the user's password. If a package requires additional packages (dependencies), you will be asked to confirm the additional packages. In this case, enter Y. After downloading and installing, the desired package is installed: Removing a package When you want to uninstall (remove) a package, you also use the apt-get command: Type the following command into a shell: $ sudo apt-get remove ace-of-penguins If asked to type the password for sudo, enter the user's password. You will be asked to confirm the removal. Enter Y. After this process, the package is removed from your system. You will have uninstalled the package ace-of-penguins. Summary In this article, we discovered the installation of a Linux operating system on the Banana Pi. Furthermore, we connected to the Banana Pi via the SSH protocol using PuTTY. Moreover, we discussed how to install new software using the Advanced Packaging Tool. This article is a combination of parts from the first two chapters of the Banana Pi Cookbook. In the Banana Pi Cookbook, we are diving more into detail and explain the specifics of the Banana Pro, for example, how to connect to the local network via WLAN. If you are using a Linux-based desktop computer, you will also learn how to set up the SD card and connect via SSH to your Banana Pi on your Linux computer. Resources for Article: Further resources on this subject: Color and motion finding [article] Controlling the Movement of a Robot with Legs [article] Develop a Digital Clock [article]
Read more
  • 0
  • 0
  • 8480

article-image-learning-beaglebone
Packt
08 May 2015
3 min read
Save for later

Learning BeagleBone

Packt
08 May 2015
3 min read
Today it is hard to deny the influence of technology in our lives. We live in an era where pretty much is automated and computerized. Among all the technological advancement that humankind has achieved, the invention of yet another important device, the BeagleBone, adds more relevance to our lives as technology progresses. Outperforming in its rudimentary stage, the BeagleBone is now equipped to deliver its promise of helping developers innovate. (For more resources related to this topic, see here.) Arranged in a chronological order, this book unfolds the amazing BeagleBone encompassing the right set of features that you need as a beginner. This collation of pages will walk you through the basics of BeagleBone boards along with exercises to guide a new user through the process of using the BeagleBone for the first time. Driving the current technology, you will find yourself at the center of innovation, programming in a standalone fashion BeagleBone White and the BeagleBone Black. As you progress, you will: Unbox a new BeagleBone Connect to external electronics with GPIO pins, analog inputs, and fast boot into Angstrom Linux Build a basic configuration of a desktop or a laptop system and program a BeagleBone board Practice simple exercises using the basic resources than what is on the board Build and refine an LED flasher Connect your BeagleBone to mobile devices Expand the BeagleBone for Bluetooth connectivity This book is directed to beginners who want to use BeagleBone as a vehicle for their learning. Makers who want to use BeagleBone to control their latest product and anyone who wants to learn to leverage current mobile technology. You can apply this knowledge on your own projects or adapt one of the many open source projects for BeagleBone. In the course of your project, you will learn more advanced techniques as you encounter hurdles. The theory presented here will provide a foundation to help surmount the challenges from your own projects. After going through the exercises in this book, thereby building an understanding of the essentials of the BeagleBone, you will not only be equipped with the tools that will magnify your capabilities, but also inspired to commence your journey in this hardware era. Now that you have a foundation, go forth and build your embedded device with the BeagleBone! Resources for Article: Further resources on this subject: Protecting GPG Keys in BeagleBone [article] Making the Unit Very Mobile - Controlling Legged Movement [article] Pulse width modulator [article]
Read more
  • 0
  • 0
  • 1376
article-image-creating-random-insults
Packt
28 Apr 2015
21 min read
Save for later

Creating Random Insults

Packt
28 Apr 2015
21 min read
In this article by Daniel Bates, the author of Raspberry Pi for Kids - Second edition, we're going to learn and use the Python programming language to generate random funny phrases such as, Alice has a smelly foot! (For more resources related to this topic, see here.) Python In this article, we are going to use the Python programming language. Almost all programming languages are capable of doing the same things, but they are usually designed with different specializations. Some languages are designed to perform one job particularly well, some are designed to run code as fast as possible, and some are designed to be easy to learn. Scratch was designed to develop animations and games, and to be easy to read and learn, but it can be difficult to manage large programs. Python is designed to be a good general-purpose language. It is easy to read and can run code much faster than Scratch. Python is a text-based language. Using it, we type the code rather than arrange building blocks. This makes it easier to go back and change the pieces of code that we have already written, and it allows us to write complex pieces of code more quickly. It does mean that we need to type our programs accurately, though—there are no limits to what we can type, but not all text will form a valid program. Even a simple spelling mistake can result in errors. Lots of tutorials and information about the available features are provided online at http://docs.python.org/2/. Learn Python the Hard Way, by Shaw Zed A., is another good learning resource, which is available at http://learnpythonthehardway.org. As an example, let's take a look at some Scratch and Python code, respectively, both of which do the same thing. Here's the Scratch code: The Python code that does the same job looks like: def count(maximum):    value = 0    while value < maximum:        value = value + 1        print "value =", value   count(5) Even if you've never seen any Python code before, you might be able to read it and tell what it does. Both the Scratch and Python code count from 0 to a maximum value, and display the value each time. The biggest difference is in the first line. Instead of waiting for a message, we define (or create) a function, and instead of sending a message, we call the function (more on how to run Python code, shortly). Notice that we include maximum as an argument to the count function. This tells Python the particular value we would like to keep as the maximum, so we can use the same code with different maximum values. The other main differences are that we have while instead of forever if, and we have print instead of say. These are just different ways of writing the same thing. Also, instead of having a block of code wrap around other blocks, we simply put an extra four spaces at the beginning of a line to show which code is contained within a particular block. Python programming To run a piece of Python code, open Python 2 from the Programming menu on the Raspberry Pi desktop and perform the following steps: Type the previous code into the window and you should notice that it can recognize how many spaces to start a line with. When you have finished the function block, press Enter a couple of times, until you see >>>. This shows that Python recognizes that your block of code has been completed, and that it is ready to receive a new command. Now, you can run your code by typing in count(5) and pressing Enter. You can change 5 to any number you like and press Enter again to count to a different number. We're now ready to create our program! The Raspberry Pi also supports Python 3, which is very similar but incompatible with Python 2. You can check out the differences between Python 2 and Python 3 at http://python-future.org/compatible_idioms.html. The program we're going to use to generate phrases As mentioned earlier, our program is going to generate random, possibly funny, phrases for us. To do this, we're going to give each phrase a common structure, and randomize the word that appears in each position. Each phrase will look like: <name> has a <adjective> <noun> Where <name> is replaced by a person's name, <adjective> is replaced by a descriptive word, and <noun> is replaced by the name of an object. This program is going to be a little larger than our previous code example, so we're going to want to save it and modify it easily. Navigate to File | New Window in Python 2. A second window will appear which starts off completely blank. We will write our code in this window, and when we run it, the results will appear in the first window. For the rest of the article, I will call the first window the Shell, and the new window the Code Editor. Remember to save your code regularly! Lists We're going to use a few different lists in our program. Lists are an important part of Python, and allow us to group together similar things. In our program, we want to have separate lists for all the possible names, adjectives, and nouns that can be used in our sentences. We can create a list in this manner: names = ["Alice", "Bob", "Carol"] Here, we have created a variable called names, which is a list. The list holds three items or elements: Alice, Bob, and Carol. We know that it is a list because the elements are surrounded by square brackets, and are separated by commas. The names need to be in quote marks to show that they are text, and not the names of variables elsewhere in the program. To access the elements in a list, we use the number which matches its position, but curiously, we start counting from zero. This is because if we know where the start of the list is stored, we know that its first element is stored at position start + 0, the second element is at position start + 1, and so on. So, Alice is at position 0 in the list, Bob is at position 1, and Carol is at position 2. We use the following code to display the first element (Alice) on the screen: print names[0] We've seen print before: it displays text on the screen. The rest of the code is the name of our list (names), and the position of the element in the list that we want surrounded by square brackets. Type these two lines of code into the Code Editor, and then navigate to Run | Run Module (or press F5). You should see Alice appear in the Shell. Feel free to play around with the names in the list or the position that is being accessed until you are comfortable with how lists work. You will need to rerun the code after each change. What happens if you choose a position that doesn't match any element in the list, such as 10? Adding randomness So far, we have complete control over which name is displayed. Let's now work on displaying a random name each time we run the program. Update your code in the Code Editor so it looks like: import random names = ["Alice", "Bob", "Carol"] position = random.randrange(3) print names[position] In the first line of the code, we import the random module. Python comes with a huge amount of code that other people have written for us, separated into different modules. Some of this code is simple, but makes life more convenient for us, and some of it is complex, allowing us to reuse other people's solutions for the challenges we face and concentrate on exactly what we want to do. In this case, we are making use of a collection of functions that deal with random behavior. We must import a module before we are able to access its contents. Information on the available modules available can be found online at www.python.org/doc/. After we've created the list of names, we then compute a random position in the list to access. The name random.randrange tells us that we are using a function called randrange, which can be found inside the random module that we imported earlier. The randrange function gives us a random whole number less than the number we provide. In this case, we provide 3 because the list has three elements and we store the random position in a new variable called position. Finally, instead of accessing a fixed element in the names list, we access the element that position refers to. If you run this code a few times, you should notice that different names are chosen randomly. Now, what happens if we want to add a fourth name, Dave, to our list? We need to update the list itself, but we also need to update the value we provide to randrange to let it know that it can give us larger numbers. Making multiple changes just to add one name can cause problems—if the program is much larger, we may forget which parts of the code need to be updated. Luckily, Python has a nice feature which allows us to make this simpler. Instead of a fixed number (such as 3), we can ask Python for the length of a list, and provide that to the randrange function. Then, whenever we update the list, Python knows exactly how long it is, and can generate suitable random numbers. Here is the code, which is updated to make it easier to change the length of the list: import random names = ["Alice", "Bob", "Carol"] length = len(names) position = random.randrange(length) print names[position] Here, we've created a new variable called length to hold the length of the list. We then use the len function (which is short for length) to compute the length of our list, and we give length to the randrange function. If you run this code, you should see that it works exactly as it did before, and it easily copes if you add or remove elements from the list. It turns out that this is such a common thing to do, that the writers of the random module have provided a function which does the same job. We can use this to simplify our code: import random names = ["Alice", "Bob", "Carol", "Dave"] print random.choice(names) As you can see, we no longer need to compute the length of the list or a random position in it: random.choice does all of this for us, and simply gives us a random element of any list we provide it with. As we will see in the next section, this is useful since we can reuse random.choice for all the different lists we want to include in our program. If you run this program, you will see that it works the same as it did before, despite being much shorter. Creating phrases Now that we can get a random element from a list, we've crossed the halfway mark to generating random sentences! Create two more lists in your program, one called adjectives, and the other called nouns. Put as many descriptive words as you like into the first one, and a selection of objects into the second. Here are the three lists I now have in my program: names = ["Alice", "Bob", "Carol", "Dave"] adjectives = ["fast", "slow", "pretty", "smelly"] nouns = ["dog", "car", "face", "foot"] Also, instead of printing our random elements immediately, let's store them in variables so that we can put them all together at the end. Remove the existing line of code with print in it, and add the following three lines after the lists have been created: name = random.choice(names) adjective = random.choice(adjectives) noun = random.choice(nouns) Now, we just need to put everything together to create a sentence. Add this line of code right at the end of the program: print name, "has a", adjective, noun Here, we've used commas to separate all of the things we want to display. The name, adjective, and noun are our variables holding the random elements of each of the lists, and "has a" is some extra text that completes the sentence. print will automatically put a space between each thing it displays (and start a new line at the end). If you ever want to prevent Python from adding a space between two items, separate them with + rather than a comma. That's it! If you run the program, you should see random phrases being displayed each time, such as Alice has a smelly foot or Carol has a fast car. Making mischief So, we have random phrases being displayed, but what if we now want to make them less random? What if you want to show your program to a friend, but make sure that it only ever says nice things about you, or bad things about them? In this section, we'll extend the program to do just that. Dictionaries The first thing we're going to do is replace one of our lists with a dictionary. A dictionary in Python uses one piece of information (a number, some text, or almost anything else) to search for another. This is a lot like the dictionaries you might be used to, where you use a word to search for its meaning. In Python, we say that we use a key to look for a value. We're going to turn our adjectives list into a dictionary. The keys will be the existing descriptive words, and the values will be tags that tell us what sort of descriptive words they are. Each adjective will be "good" or "bad". My adjectives list becomes the following dictionary. Make similar changes to yours. adjectives = {"fast":"good", "slow":"bad", "pretty":"good", "smelly":"bad"} As you can see, the square brackets from the list become curly braces when you create a dictionary. The elements are still separated by commas, but now each element is a key-value pair with the adjective first, then a colon, and then the type of adjective it is. To access a value in a dictionary, we no longer use the number which matches its position. Instead, we use the key with which it is paired. So, as an example, the following code will display "good" because "pretty" is paired with "good" in the adjectives dictionary: print adjectives["pretty"] If you try to run your program now, you'll get an error which mentions random.choice(adjectives). This is because random.choice expects to be given a list, but is now being given a dictionary. To get the code working as it was before, replace that line of code with this: adjective = random.choice(adjectives.keys()) The addition of .keys() means that we only look at the keys in the dictionary—these are the adjectives we were using before, so the code should work as it did previously. Test it out now to make sure. Loops You may remember the forever and repeat code blocks in Scratch. In this section, we're going to use Python's versions of these to repeatedly choose random items from our dictionary until we find one which is tagged as "good". A loop is the general programming term for this repetition—if you walk around a loop, you will repeat the same path over and over again, and it is the same with loops in programming languages. Here is some code, which finds an adjective and is tagged as "good". Replace your existing adjective = line of code with these lines: while True:    adjective = random.choice(adjectives.keys())    if adjectives[adjective] == "good":        break The first line creates our loop. It contains the while key word, and a test to see whether the code should be executed inside the loop. In this case, we make the test True, so it always passes, and we always execute the code inside. We end the line with a colon to show that this is the beginning of a block of code. While in Scratch we could drag code blocks inside of the forever or repeat blocks, in Python we need to show which code is inside the block in a different way. First, we put a colon at the end of the line, and then we indent any code which we want to repeat by four spaces. The second line is the code we had before: we choose a random adjective from our dictionary. The third line uses adjectives[adjective] to look into the (adjectives) dictionary for the tag of our chosen adjective. We compare the tag with "good" using the double = sign (a double = is needed to make the comparison different from the single = case, which stores a value in a variable). Finally, if the tag matches "good",we enter another block of code: we put a colon at the end of the line, and the following code is indented by another four spaces. This behaves the same way as the Scratch if block. The fourth line contains a single word: break. This is used to escape from loops, which is what we want to do now that we have found a "good" adjective. If you run your code a few times now, you should see that none of the bad adjectives ever appear. Conditionals In the preceding section, we saw a simple use of the if statement to control when some code was executed. Now, we're going to do something a little more complex. Let's say we want to give Alice a good adjective, but give Bob a bad adjective. For everyone else, we don't mind if their adjective is good or bad. The code we already have to choose an adjective is perfect for Alice: we always want a good adjective. We just need to make sure that it only runs if our random phrase generator has chosen Alice as its random person. To do this, we need to put all the code for choosing an adjective within another if statement, as shown here: if name == "Alice":    while True:        adjective = random.choice(adjectives.keys())        if adjectives[adjective] == "good":            break Remember to indent everything inside the if statement by an extra four spaces. Next, we want a very similar piece of code for Bob, but also want to make sure that the adjective is bad: elif name == "Bob":    while True:        adjective = random.choice(adjectives.keys())        if adjectives[adjective] == "bad":           break The only differences between this and Alice's code is that the name has changed to "Bob", the target tag has changed to "bad", and if has changed to elif. The word elif in the code is short for else if. We use this version because we only want to do this test if the first test (with Alice) fails. This makes a lot of sense if we look at the code as a whole: if our random person is Alice, do something, else if our random person is Bob, do something else. Finally, we want some code that can deal with everyone else. This time, we don't want to perform another test, so we don't need an if statement: we can just use else: else:    adjective = random.choice(adjectives.keys()) With this, our program does everything we wanted it to do. It generates random phrases, and we can even customize what sort of phrase each person gets. You can add as many extra elif blocks to your program as you like, so as to customize it for different people. Functions In this section, we're not going to change the behavior of our program at all; we're just going to tidy it up a bit. You may have noticed that when customizing the types of adjectives for different people, you created multiple sections of code, which were almost identical. This isn't a very good way of programming because if we ever want to change the way we choose adjectives, we will have to do it multiple times, and this makes it much easier to make mistakes or forget to make a change somewhere. What we want is a single piece of code, which does the job we want it to do, and then be able to use it multiple times. We call this piece of code a function. We saw an example of a function being created in the comparison with Scratch at the beginning of this article, and we've used a few functions from the random module already. A function can take some inputs (called arguments) and does some computation with them to produce a result, which it returns. Here is a function which chooses an adjective for us with a given tag: def chooseAdjective(tag):    while True:        item = random.choice(adjectives.keys())        if adjectives[item] == tag:            break    return item In the first line, we use def to say that we are defining a new function. We also give the function's name and the names of its arguments in brackets. We separate the arguments by commas if there is more than one of them. At the end of the line, we have a colon to show that we are entering a new code block, and the rest of the code in the function is indented by four spaces. The next four lines should look very familiar to you—they are almost identical to the code we had before. The only difference is that instead of comparing with "good" or "bad", we compare with the tag argument. When we use this function, we will set tag to an appropriate value. The final line returns the suitable adjective we've found. Pay attention to its indentation. The line of code is inside the function, but not inside the while loop (we don't want to return every item we check), so it is only indented by four spaces in total. Type the code for this function anywhere above the existing code, which chooses the adjective; the function needs to exist in the code prior to the place where we use it. In particular, in Python, we tend to place our code in the following order: Imports Functions Variables Rest of the code This allows us to use our functions when creating the variables. So, place your function just after the import statement, but before the lists. We can now use this function instead of the several lines of code that we were using before. The code I'm going to use to choose the adjective now becomes: if name == "Alice":    adjective = chooseAdjective("good") elif name == "Bob":    adjective = chooseAdjective("bad") else:    adjective = random.choice(adjectives.keys()) This looks much neater! Now, if we ever want to change how an adjective is chosen, we just need to change the chooseAdjective function, and the change will be seen in every part of the code where the function is used. Complete code listing Here is the final code you should have when you have completed this article. You can use this code listing to check that you have everything in the right order, or look for other problems in your code. Of course, you are free to change the contents of the lists and dictionaries to whatever you like; this is only an example: import random   def chooseAdjective(tag):    while True:        item = random.choice(adjectives.keys())        if adjectives[item] == tag:            break    return item   names = ["Alice", "Bob", "Carol", "Dave"] adjectives = {"fast":"good", "slow":"bad", "pretty":"good", "smelly":"bad"} nouns = ["dog", "car", "face", "foot"]   name = random.choice(names) #adjective = random.choice(adjectives) noun = random.choice(nouns)   if name == "Alice":    adjective = chooseAdjective("good") elif name == "Bob":    adjective = chooseAdjective("bad") else:    adjective = random.choice(adjectives.keys())   print name, "has a", adjective, noun Summary In this article, we learned about the Python programming language and how it can be used to create random phrases. We saw that it shared lots of features with Scratch, but is simply presented differently. Resources for Article: Further resources on this subject: Develop a Digital Clock [article] GPS-enabled Time-lapse Recorder [article] The Raspberry Pi and Raspbian [article]
Read more
  • 0
  • 0
  • 3095

article-image-gps-enabled-time-lapse-recorder
Packt
23 Mar 2015
17 min read
Save for later

GPS-enabled Time-lapse Recorder

Packt
23 Mar 2015
17 min read
In this article by Dan Nixon, the author of the book Raspberry Pi Blueprints, we will see the recording of time-lapse captures using the Raspberry Pi camera module. (For more resources related to this topic, see here.) One of the possible uses of the Raspberry Pi camera module is the recording of time-lapse captures, which takes a still image at a set interval over a long period of time. This can then be used to create an accelerated video of a long-term event that takes place (for example, a building being constructed). One alteration to this is to have the camera mounted on a moving vehicle. Use the time lapse to record a journey; with the addition of GPS data, this can provide an interesting record of a reasonably long journey. In this article, we will use the Raspberry Pi camera module board to create a location-aware time-lapse recorder that will store the GPS position with each image in the EXIF metadata. To do this, we will use a GPS module that connects to the Pi over the serial connection on the GPIO port and a custom Python program that listens for new GPS data during the time lapse. For this project, we will use the Raspbian distribution. What you will need This is a list of things that you will need to complete this project. All of these are available at most electronic components stores and online retailers: The Raspberry Pi A relatively large SD card (at least 8 GB is recommended) The Pi camera board A GPS module (http://www.adafruit.com/product/746) 0.1 inch female to female pin jumper wires A USB power bank (this is optional and is used to power the Pi when no other power is available) Setting up the hardware The first thing we will do is set up the two pieces of hardware and verify that they are working correctly before moving on to the software. The camera board The first (and the most important) piece of hardware we need is the camera board. Firstly, start by connecting the camera board to the Pi. Connecting the camera module to the Pi The camera is connected to the Pi via a 15-pin flat, flex ribbon cable, which can be physically connected to two connectors on the Pi. However, the connector it should be connected to is the one nearest to the Ethernet jack; the other connector is for display. To connect the cable first, lift the top retention clip on the connector, as shown in the following image: Insert the flat, flex cable with the silver contacts facing the HDMI port and the rigid, blue plastic part of the ribbon connector facing the Ethernet port on the Pi: Finally, press down the cable retention clip to secure the cable into the connector. If this is done correctly, the cable should be perpendicular to the printed circuit board (PCB) and should remain seated in the connector if you try to use a little force to pull it out: Next, we will move on to set up the camera driver, libraries, and software within Raspbian. Setting up the Raspberry Pi camera Firstly, we need to enable support for the camera in the operating system itself by performing the following steps: This is done by the raspi-config utility from a terminal (either locally or over SSH). Enter the following command: sudo raspi-config This command will open the following configuration page: This will load the configuration utility. Scroll down to the Enable Camera option using the arrow keys and select it using Enter. Next, highlight Enable and select it using Enter: Once this is done, you will be taken back to the main raspi-config menu. Exitraspi-config, and reboot the Pi to continue. Next, we will look for any updates to the Pi kernel, as using an out-of-date kernel can sometimes cause issues with the low-level hardware, such as the camera module and GPIO. We also need to get a library that allows control of the camera from Python. Both of these installations can be done with the following two commands: sudo rpi-update sudo apt-get install python-picamera Once this is complete, reboot the Pi using the following command: sudo reboot Next, we will test out the camera using the python-picamera library we just installed.To do this, create a simple test script using nano: nano canera_test.py The following code will capture a still image after opening the preview for 5 seconds. Having the preview open before a capture is a good idea as this gives the camera time to adjust capture parameters of the environment: import sys import time import picamera with picamera.PiCamera() as cam:    cam.resolution = (1280, 1024)    cam.start_preview()    time.sleep(5)    cam.capture(sys.argv[1])    cam.stop_preview() Save the script using Ctrl + X and enter Y to confirm. Now, test it by using the following command: python camera_test.py image.jpg This will capture a single, still image and save it to image.jpg. It is worth downloading the image using SFTP to verify that the camera is working properly. The GPS module Before connecting the GPS module to the Pi, there are a couple of important modifications that need to be made to the way the Pi boots up. By default, Raspbian uses the on-board serial port on the GPIO header as a serial terminal for the Pi (this allows you to connect to the Pi and run commands in a similar way to SSH). However, this is of little use to us here and can interfere with the communication between the GPS module and the Pi if the serial terminal is left enabled. This can be disabled by modifying a couple of configuration files: First, start with: sudo nano /boot/cmdline.txt Here, you will need to remove any references to ttyAMA0 (the name for the on-board serial port). In my case, there was a single entry of console=ttyAMA0,115200, which had to be removed. Once this is done, the file should look something like what is shown in the following screenshot: Next, we need to stop the Pi by using the serial port for the TTY session. To do this, edit this file: sudo nano /etc/inittab Here, look for the following line and comment it out: T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100 Once this is done, the file should look like what is shown in the following screenshot: After both the files are changed, power down the Pi using the following command: sudo shutdown -h now Next, we need to connect the GPS module to the Pi GPIO port. One important thing to note when you do this is that the GPS module must be able to run on 3.3 V or at least be able to use a 3.3 V logic level (such as the Adafruit module I am using here). As with any device that connects to the Pi GPIO header, using a 5 V logic device can cause irreparable damage to the Pi. Next, connect the GPS module to the Pi, as shown in the following diagram. If you are using the Adafruit module, then all the pins are labeled on the PCB itself. For other modules, you may need to check the data sheet to find which pins to connect: Once this is completed, the wiring to the GPS module should look similar to what is shown in the following image: After the GPS module is connected and the Pi is powered up, we will install, configure, and test the driver and libraries that are needed to access the data that is sent to the Pi from the GPS module: Start by installing some required packages. Here, gpsd is the daemon that managed data from GPS devices connected to a system, gpsd-clients contains a client that we will use to test the GPS module, and python-gps contains the Python client for gpsd, which is used in the time-lapse capture application: sudo apt-get install gpsd gpsd-clients python-gps Once they are installed, we need to configure gpsd to work in the way we want. To do this, use the following command: sudo dpkg-reconfigure gpsd This will open a configuration page similar to raspi-config. First, you will be asked whether you want gpsd to start on boot. Select Yes here: Next, it will ask whether we are using USB GPS receivers. Since we are not using one, select No here: Next, it will ask for the device (that is, serial port) the GPS receiver is connected to. Since we are using the on-board serial port on the Pi GPIO header, enter /dev/ttyAMA0 here: Next, it will ask for any custom parameters to pass to gpsd, when it is executed. Here, we will enter -n -G. -n, which tells gpsd to poll the GPS module even before a client has requested any data (this has been known to cause problems with some applications) and -G tells gpsd to accept connections from devices other then the Pi itself (this is not really required, but is a good debugging tool): When you start gpsd with the -G option, you can then use cgps to view the GPS data from any device by using the command where [IP] is the IP address of the Pi: cgps [IP] Finally, you will be asked for the location of the control socket. The default value should be kept here so just select Ok: After the configuration is done, reboot the Pi and use the following command to test the configuration: cgps -s This should give output similar to what is shown in the following screenshot, if everything works: If the status indication reads NO FIX, then you may need to move the GPS module into an area with a clear view of the sky for testing. If cgps times out and exits, then gpsd has failed to communicate with your GPS module. Go back and double-check the configuration and wiring. Setting up the capture software Now, we need to get the capture software installed on the Pi. First, copy the recorder folder onto the Pi using FileZilla and SFTP. We need to install some packages and Python libraries that are used by the capture application. To do this, first install the Python setup tools that I have used to package the capture application: sudo apt-get install python-setuptools git Next, run the following commands to download and install the pexif library, which is used to save the GPS position from which each image was taken into the image EXIF data: git clone https://github.com/bennoleslie/pexif.git pexif cd pexif sudo python setup.py install Once this is done, SSH into the Pi can change directory to the recorder folder and run the following command: sudo python setup.py install Now that the application is installed, we can take a look at the list of commands it accepts using: gpstimelapse -h This shows the list of commands, as shown in the following screenshot: A few of the options here can be ignored; --log-file, --log-level, and --verbose were mainly added for debugging while I was writing the application. The --gps option will not need to be set, as it defaults to connect to the local gpsd instance, which if the application is running on the Pi, will always be correct. The --width and --height options are simply used to set the resolution of the captured image. Without them, the capture software will default to capture 1248 x 1024 images. The --interval option is used to specify how long, in seconds, to wait before it captures another time-lapse frame. It is recommended that you set this value at least 10 seconds in order to avoid filling the SD card too quickly (especially if the time lapse will run over a long period of time) and to ensure that any video created with the frames is of a reasonably length (that is, not too long). The --distance option allows you to specify a minimum distance, in kilometers, that must be travelled since the last image was captured and before another image is captured. This can be useful to record a time lapse where, whatever holds the Pi, may stop in the same position for periods of time (for example, if the camera is in a car dashboard, this would prevent it from capturing several identical frames if the car is waiting in traffic). This option can also be used to capture a set of images based alone on the distance travelled, disregarding the amount of time that has passed. This can be done by setting the --interval option to 1 (a value of 1 is used as data is only taken from the GPS module every second, so checking the distance travelled faster than this would be a waste of time). The folder structure is used to store the frames. While being slightly complex at first sight, this is a good method that allows you to take multiple captures without ever having to SSH into the Pi. Using the --folder option, you can set the folder under which all captures are saved. In this folder, the application looks for folders with a numerical name and creates a new folder that is one higher than the highest number it finds. This is where it will save the images for the current capture. The filename for each image is given by the --filename option. This option specifies the filename of each image that will be captured. It must contain %d, which is used to indicate the frame number (for example, image_%d.jpg). For example, if I pass --folder captures --filename image_%d.jpg to the program, the first frame will be saved as ./captures/0/image_0/jpg, and the second as ./captures/0/image_1.jpg. Here are some examples of how the application can be used: gpstimelapse --folder captures --filename i_%d.jpg --interval 30: This will capture a frame in every 30 seconds gpstimelapse --folder captures --filename i_%d.jpg --interval 30 --distance 0.05: This will capture a frame in every 30 seconds, provided that 50 meters have been travelled gpstimelapse --folder captures --filename i_%d.jpg --interval 1 --distance 0.05: This will capture a frame in every 50 meters that have been travelled Now that you are able to run the time-lapse recorder application, you are ready to configure it to start as soon as the Pi boots. Removing the need for an active network connection and the ability to interface with the Pi to start the capture. To do this, we will add a command to the /etc/rc.local file. This can be edited using the following command: sudo nano /etc/rc.local The line you will add will depend on how exactly you want the recorder to behave. In this case, I have set it to record an image at the default resolution every minute. As before, ensure that the command is placed just before the line containing exit 0: Now, you can reboot the Pi and test out the recorder. A good indication that the capture is working is the red LED on the camera board that lights up constantly. This shows that the camera preview is open, which should always be the case with this application. Also note that, the capture will not begin until the GPS module has a fix. On the Adafruit module, this is indicated by a quick blink every 15 seconds on the fix LED (no fix is indicated by a steady blink once per second). One issue you may have with this project is the amount of power required to power the camera and GPS module on top of the Pi. To power this while on the move, I recommend that you use one of the USB power banks that have a 2 A output (such power banks are readily available on Amazon). Using the captures Now that we have a set of recorded time-lapse frames, where each has a GPS position attached, there are a number of things that can be done with this data. Here, we will have a quick look at a couple of instances for which we can use the captured frames. Creating a time-lapse video The first and probably the most obvious thing that can be done with the images is you can create a time-lapse video in which, each time-lapse image is shown as a single frame of the video, and the length (or speed) of the video is controlled by changing the number of frames per second. One of the simplest ways to do this is by using either the ffmpeg or avconv utility (depending on your version of Linux; the parameters to each are identical in our case). This utility is available on most Linux distributions, including Raspbian. There are also precompiled executables available for Mac and Windows. However, here I will only discuss using it on Linux, but rest assured, any instructions given here will also work on the Pi itself. To create a time lapse, form a set of images. You can use the following command: avconv -framerate FPS -i FILENAME -c:v libx264 -r 30 -pix_fmt yuv420p OUTPUT Here, FPS is the number of the time-lapse frames you want to display every second, FILENAME is the filename format with %d that marks the frame number, and OUTPUT is the output's filename. This will give output similar to the following: Exporting GPS data as CSV We can also extract GPS data from each of the captured time-lapse images and save it as a comma-separated value (CSV) file. This will allow us to import the data into third-party applications, such as Google Maps and Google Earth. To do this, we can use the frames_to_gps_path.py Python script. This takes the file format for the time-lapse frames and a name for the output file. For example, to create a CSV file called gps_data.csv for images in the frame_%d.jpg format, you can use the following command: python frames_to_gps_points.py -f frame_%d.jpg -o gps_points.csv The output is a CSV file in the following format: [frame number],[latitude],[longitude],[image filename] The script also has the option to restrict the maximum number of output points. Passing the --max-points N parameter will ensure that no more than N points are in the CSV file. This can be useful for importing data into applications that limit the number of points that can be imported. Summary In this article, we had a look at how to use the serial interface on the GPIO port in order to interface with some external hardware. The knowledge of how to do this will allow you to interface the Pi with a much wider range of hardware in future projects. We also took a look at the camera board and how it can be used from within Python. This camera is a very versatile device and has a very wide range of uses in portable projects and ubiquitous computing. You are encouraged to take a deeper look at the source code for the time-lapse recorder application. This will get you on your way to understand the structure of moderately complex Python programs and the way they can be packaged and distributed. Resources for Article: Further resources on this subject: Central Air and Heating Thermostat [article] Raspberry Pi Gaming Operating Systems [article] The Raspberry Pi and Raspbian [article]
Read more
  • 0
  • 0
  • 2723