1 Line PHP Servers for Raspberry Pi Projects

I wanted to introduce my daughters to using PHP on Raspberry Pi Projects. My goal has been to try and keep things super minimalist so that they can quickly pull together a project for school without being overwhelmed with installation or dependency issues.

In this blog I will look at:

  • Running a 1-Line PHP server (no other web server will be used or installed)
  • Show Bash diagnostics tools on a PHP page (3 lines of PHP)
  • Use a PHP calls to read/write Rasp Pi GPIO pins

Loading and Running a PHP Server

Typically PHP is loaded with Web server applications like Apache, but PHP can be run as a standalone application. To install PHP on a Raspberry Pi or Ubuntu system:

sudo apt-get install php -y

The syntax to run PHP as a standalone web server:

php -S <addr>:<port> [-t docroot] startpage

# for example
php -S 192.168.0.111:8080 mypage.htm

# to use Bash to get your IP
php -S $(hostname -I | awk '{print $1 ":8080"}') mypage.htm 

It’s important to note that the standalone PHP server is designed for testing and very small projects. It should not be used for any kind of production environment.

Superquick PHP Primer

PHP is an extremely popular Web programming language.

PHP originally stood for : Personal Home Page, but after a lot of enhancements it now stands for: “PHP: Hypertext Preprocessor”.

A PHP file normally contains HTML tags, and some PHP scripting code. A PHP script starts with “<?php” and ends with “?>“. An example would be (test1.php) :

<!DOCTYPE html>
<html>
<body>

<h1>A PHP Test Page</h1>

<?php
// This is PHP script block
$a = 4;
$b = 6;
echo "Hello World! ";
echo "4 x 6 =" . ($a * $b);
?>
<p>Below is a single line of PHP</p>
<?php echo "This is a single line" ?>

</body>
</html>

To learn about the PHP syntax there are some good references.

To run this page:

php -S $(hostname -I | awk '{print $1 ") test1.php

It’s useful to know that PHP code can be run directly with the PHP interpreter:

# A single line of PHP (note: -r for single line)
$ php -r '$a=4; $b=5; echo  $a * $b . "\n" ; '
20

# Run a PHP script 
$ php test1.php

<!DOCTYPE html>
<html>
<body>

<h1>A PHP Test Page</h1>

Hello World! 4 x 6 =24<p>Below is a single line of PHP</p>
This is a single line
</body>
</html> 

Command line Diagnostics on a Web Page

Linux command line utilities can have their output viewable on a Web page. The example below (vmstats.php) uses the PHP shell_exec call to execute the vmstat command line utility and the results are echoed to the web page. The <pre> tag is used to present the results in fixed-width font.

<?php
// vmstats.php - A PHP test page to some CPU stats 
echo "<pre>";
echo shell_exec('vmstat');
echo "</pre>";
?>

A 1 line PHP web server command to call this page is:

php -S $(hostname -I | awk '{print $1 ":8080") vmstats.php

PHP Interfacing to Pi GPIO

There are a few ways to access the GPIO pins in PHP:
1. use a PHP library
2. shell to the gpio command

Using a PHP library allows for a standard PHP interface, with an object model.

However from testing I found that the PHP libraries were not as flexible as the standard gpio command. For example you could not access extended GPIO pin numbers (i.e. 200).

GPIO Command Line Utility

PHP can shell out to the gpio command line utility. I liked this approach because I could test the actions manually before putting them into a PHP web page.

A simple gpio read example would be:

<html lang="en">
<head>
</head>
<body>
<?php
$ret = shell_exec('gpio read 7');
echo "Pin 7 status = " . $ret;
?>
</body>
</html>

And a gpio write example (with reading back the result) would be:

<html>
<head>
</head>
<body>
<?php
exec("gpio write 7 1");
$ret = shell_exec('gpio read 7');
echo "Pin 7 status = " . $ret;
?>
</body>
</html>

Control A Pi Rover using PHP

The Raspberry Pi rover project is a good example that pulls together:

  • Control of Pi GPIO pins
  • PHP Forms
  • Cascading Style Sheets (CSS) for mobile phone presentations

Motors should not be connected directly to a Raspberry Pi because they could potential damage the Pi hardware. It is recommended that some intermediate equipment or a motor top be used. For this project we used a Pimoroni ExplorerHat Pro.

PHP Forms

This example uses an HTML post method that is defined in the <form> tag. The buttons pass the values of: go, stop, left and right.

The PHP code look for the post value and then does a gpio write for the required action. For example a go will turn on both GPIO motor pins.

The full PHP code is below:

<?php
// rover.php - control Rasp Pi GPIO pins using PHP form with buttons
//

// adjust pins for the specific motor setup 
$leftpin = 7;
$rightpin = 2;

// Get post feedback message
if (isset($_POST['submit'])) {
	switch ($_POST['submit']) {
		case "go":
			exec("gpio write " . $leftpin . " 1");
			exec("gpio write " . $rightpin . " 1");
			break;
		case "stop":
			exec("gpio write " . $leftpin . " 0");
			exec("gpio write " . $rightpin . " 0");
			break;
		case "left":
			exec("gpio write " . $leftpin . " 1");
			exec("gpio write " . $rightpin . " 0");
			break;
		case "right":
			exec("gpio write " . $leftpin . " 0");
			exec("gpio write " . $rightpin . " 1");
			break;
	}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <title>PHP/Pi Rover Controls</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">

  <h2>PI Four Button Example</h2>
  <form action="" method="post">
    <div class="form-group">

    <button type="submit" name="submit" class="btn-success btn-lg" style="width:100%" value="go">Forward</button>
    <button type="submit" name="submit" class="btn-info btn-lg" style="width:49%" value="left">Left</button>
    <button type="submit" name="submit" class="btn-info btn-lg" style="width:49%" value="right">Right</button>
    <button type="submit" name="submit" class="btn-danger btn-lg" style="width:100%" value="stop">Stop</button>
  </form>
</div>

</body>
</html>

Mobile CCS Templates

There are quite a few good mobile templates to choose from. Bootstrap (http://getbootstrap.com/) is one of the most popular frameworks, and for Pi applications it seems to be a good fit.

Some of the key items are:

  • Add references in to the bootstrap ccs and js files
  • Add tags with the required class definitions:
    • the btn-lg class will make a large button, instead of standard sized btn 
    • different button colours are possible using btn-info, btn-success. btn-danger
    • Button width is defined with style=”width: xx%” . For multiple buttons the sum of the width needs to <100%

Further Examples

Below are some pictures of a mobile rocket launcher project.  The Web page had two sections. The top section controlled bi-directional motors that were connected to a Explorer HAT Pro shield. The bottom section controlled the rocket launcher turret. The missile launcher was connected via a USB cable to the Pi.

Screenshot
OLYMPUS DIGITAL CAMERA

 

 

Tow Truck

The goal for our tow truck was to have a 4-axis crane and a movable vehicle that we could remotely control with an Android smart phone.

tow_truck2

The parts we used for this project were:

Hardware Setup

The tow truck project used a camera mount for up/down/left/right crane motion and an Arduino car chassis for mobility. The controls were done using Bluetooth.

Meccano was used to build a box for the main structure. Wire was used to secure everything together. We laid a folded piece of paper under the Arduino Mega to ensure that none of the Arduino solder connections shorted on the metal Meccano base.

tow_truck_inside

The motor and servo shield that we used did not expose any of the extra Arduino pins, so we needed to use the Mega board. We then wired the Bluetooth module to the exposed pins on the end of the Mega.

tow_truck_circuit

Arduino Code

The Arduino code will vary a little based on the motor/servo shield that is used. Our shield was an older version 1 (V1) board that used direct pin connections (no I2C or SDA/SCL connections).

Also because Tx/Rx (Tx0/Rx)) were not available once our motor/servo shield was installed we used Tx1/Rx1 and so our Bluetooth connection was on Serial1 and not Serial.

For the Bluetooth communications we used the following command letters:

  • R = drive right
  • L = drive left
  • f = drive forwards
  • b = drive backwards
  • s = stop driving
  • r = move crane right
  • l = move crane left
  • u= move crane up
  • d = move crane down

Our Arduino code is below:

#include <Servo.h> 

Servo servo1;
Servo servo2;

char thecmd;
int xpos = 90;
int ypos = 90;

AF_DCMotor motor1(1); 
AF_DCMotor motor2(2);

void setup() {
  pinMode( 19, INPUT_PULLUP );
  Serial1.begin(9600);
  Serial1.println("Crane Controls");
  Serial1.println("r = right, l = left, u= up, d = down");
  Serial1.println("Driving Controls");
  Serial1.println("R = right, L = left, f = forwards, b = backwards, s = stop");
  servo1.attach(9); // attaches the servo on pin 9 to the servo object 
  servo2.attach(10); // attaches the servo on pin 9 to the servo object 
  
  servo1.write(xpos);
  servo2.write(ypos);

  motor1.setSpeed(255);
  motor2.setSpeed(255);

}
void loop() {
  
  if (Serial1.available() > 0) {
        // read the incoming byte: 
       thecmd = Serial1.read();
       Serial1.println(thecmd);
       if (thecmd =='l') { move_crane(servo1, 5); }
       if (thecmd =='r') { move_crane(servo1, -5); }
       if (thecmd =='d') { move_crane(servo2, 5); }
       if (thecmd =='u') { move_crane(servo2, -5); }
       if (thecmd =='f') { 
            motor1.run(FORWARD); 
            motor2.run(FORWARD); 
       }
        if (thecmd =='b') { 
            motor1.run(BACKWARD); 
            motor2.run(BACKWARD); 
       }
       if (thecmd =='L') { 
           motor1.run(BACKWARD); 
           motor2.run(FORWARD); 
       }
       if (thecmd =='R') { 
            motor1.run(FORWARD); 
            motor2.run(BACKWARD); 
       }
       if (thecmd =='s') { 
           motor1.run(RELEASE); 
           motor2.run(RELEASE); 
       }
  }
}

void move_crane(Servo theservo, int direction) {
  int minpos = 50;
  int maxpos = 220;
  if (direction < 0) {
    if (ypos > minpos) {
      ypos = ypos + direction;
      theservo.write(ypos);
    }
  }
  else {
    if (ypos < maxpos) {
      ypos = ypos + direction;
      theservo.write(ypos); 
    }   
  }
}

Android Program

To communication to an Android smart phone we used MIT’s App inventor. This is a free Web based Android development tool.

There are many ways to layout a control screen, for us we used a 10×3 table and then populated it with buttons. Our layout is shown below:

ai_layout

The button logic will pass the required letter command to the Bluetooth component:

ai_logic

Our final running App looked like:

Screenshot_tow_truck

Pi Node-Red Streetcar

For our streetcar design we wanted to :

  • manually control things with a Web interface on a smart phone, and
  • automatically have the streetcar stop at station, wait, then go in the reverse direction.

For this project we built everything in Lego, with Lego Mindstorm components. The programming was done in Node-Red which was running on a Raspberry Pi.

The Lego Mindstorms EV3 and NXT components can be wired into your Pi (or Arduino) projects by using some custom adapters. If you are brave you could cut one end off of the connector cables. We unfortunately didn’t have any extra cables so went the safe route with the adapters. There are a couple of different adapters that are available we used the breadboard version from Dexter Industries.

Using the following parts we were able to make an automated streetcar :

  • 1 Lego Mindstorms motor
  • 1 Lego Mindstorms touch sensors
  • 3 Lego Mindstorms connector cables
  • 3 Dexter Lego Mindstorms bread board adapter
  • 1 small breadboard
  • 1 Pi 3 (or Pi 2 with a network connection)
  • 1 Pimoroni ExplorerPro Hat
  • 2 long pieces of wire
  • lots of Lego blocks

Streetcar Design

Our goal for the streetcar project was to have two stations, then have the streetcar automatically stop and switch directions at each station.

full_street

Station 1 had the motor, a touch sensor, and the Raspberry Pi.

station1

Station 2 had a pulley wheel, a touch sensor and a small breadboard that wired back to the Pi at station 1. Our pulley string went above the streetcar. We needed to keep the string quite tight so the pulley would not slip.

station2_top1

The Wiring

All of the Lego Mindstorms wiring used the same pins on the left side of the connector. and they are labeled “ANG” and “GND”. We used an ExplorerHat Pro to connect the Lego Mindstorms Motor and touch sensors to the Raspberry Pi. As we mentioned earlier the station 2 touch sensor was wired into a small breadboard and then from there two wires connected it to the ExplorerPro. For our setup station 1 touch sensor was wired on Explorer Pro input 1, and station 2 was on input 2.

circuit

Node-Red Installation

To check that Node-Red is installed and working, go to a Terminal window and enter:

node-red-start &

If you are able to run Node-Red, the next step is to install the Pimoroni ExplorerHat node and a web dashboard node. Depending on your installation you might need to load the Node Package Manager, npm :

sudo apt-get update
sudo apt-get install npm

Then to install the added libraries:

\curl -sS get.pimoroni.com/explorerhat | bash
 cd ~/.node-red
 npm install node-red-contrib-explorerhat
 npm install node-red-dashboard

After you install these library nodes you will need to restart your Pi. Once Node-RED restarts, you use a web browser to build applications. If you are working directly on your Pi, enter 127.0.0.1:1880 in the URL address box of your browser.

Node-Red Manual Web Control

To make a web based manual control program, drag three button nodes from the left node panel onto the center panel. Then wire the button nodes to an ExplorerHat output node.

nr2

Double click on a button node to open an edit window. The edit window allows you to configure the dashboard, labels and button actions. To control the first ExplorerHat motor the topic is motor.one. The payload is between -100 and 100, and this corresponds to full reverse and full forward, with 0 being stopped.

After you have finished all your Node-Red configure click the Deploy button at the top right of your browser window. Deploying will run your program and enable the web dashboards. To access the web dashboards enter: http://your-ip-address:1880/ui. If you are unsure of your IP address go to a terminal window and enter : ifconfig.

screenshot

Node-Red Automatic Control Program

We found the automatic control logic to be a little tricker than the manual logic. Our first step was to see if we could read the Lego Mindstorms touch sensors. For this we connected an ExplorerHAT input node to a debug node. We manually pushed each touch sensor and we used the debug tab to check the results.

debug

To catch when the streetcar hits the touch sensor at station 1 we needed to create a function that looked at the topic explorerhat/input.1. If this topic’s playload is 1 or pushed then the ExplorerHat motor can be stopped by sending a message with the topic of motor.one and the payload=0. A similar function is created for the touch sensor at station 2 except the topic explorerhat/input.2 is monitored.

button1

After the streetcar hits a touch sensor we wanted it to pause, and then move in the opposite direction. A delay node was used for the pause. Following this a function node is used to send a message with a payload of the new speed and direction. For our project station 1 restarted with a speed of -70, and station 2 restarted with a speed of 70 (or +70).

reverse1

Our complete logic with both manual and automatic control is shown below:

full_logic

Remote Controlled Rocket Launcher

We’ve made a number of different versions of the mobile rocket launcher, and all of them have been fun. The version above is using the a PI 1 with a PiFace Digital module for the motor controls and a wireless keyboard for the controls.

The version shown below is using a PI 3, with an ExploreHAT Pro for the motor controls and a Python Web Server program for the controls. By using some simplified HTML tagging we were able to use an old PSP as a remote interface console.

launcher

Rocket Launcher Sample Code

We found the rocket launcher in a sale bin, but they call be purchased at: http://dreamcheeky.com/thunder-missile-launcher. The rocket launcher comes with it’s own Windows based program.

Below is some Python code that will control the rockets launchers turret and fire a missile. Based on this sample code you should be able to make some cool projects. A couple of notes from our testing:

  • you need to manually stop the turret motion once you start it. So you need to set your own wait time
  • you need 3-4 seconds between each missile firing. It might be a coincident but we damaged our first rocket launcher trying to issue fast firing commands.
 import usb
import sys
import time

device = usb.core.find(idVendor=0x2123, idProduct=0x1010)

# On Linux we need to detach usb HID first
try:
device.detach_kernel_driver(0)
# except Exception, e:
except Exception:

pass # already unregistered

device.set_configuration()

endpoint = device[0][(0,0)][0]

down = 1 # down
up = 2 # up
left = 4 # rotate left
right = 8 # rotate right
fire = 16 # fire
stop = 32 # stop

#device.ctrl_transfer(0x21, 0x09, 0x0200, 0, [signal])

while True:

print('r = right, l = left, u = up, d = down, f = fire ')
key = raw_input ('enter key:')
if (key == 'l'):
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, left, 0x00,0x00,0x00,0x00,0x00,0x00])
if (key == 'u'):
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, up, 0x00,0x00,0x00,0x00,0x00,0x00])
if (key == 'r'):
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, right, 0x00,0x00,0x00,0x00,0x00,0x00])
if (key == 'd'):
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, down, 0x00,0x00,0x00,0x00,0x00,0x00])
if (key == 'f'):
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, fire, 0x00,0x00,0x00,0x00,0x00,0x00])
time.sleep(4)
time.sleep(0.1)
device.ctrl_transfer(0x21, 0x09, 0, 0, [0x02, stop, 0x00,0x00,0x00,0x00,0x00,0x00]) 

 

 

 

PSP Controlled Arduino Airboat

We thought that it would be fun to try and use an old PlayStation Portable (PSP) on some Arduino and Pi Projects. If you don’t a have PSP you can usually find a used one at a good price.

Some smart people were able to modify or “mod” the PSP firmware so that it is possible to run open source applications on the PSP. We tried using Python, Lua, sdlBasic and SSH to talk between our PSP  and our Arduinos and Pi’s, but none of these methods were simple or 100% reliable. In the end we found that basic built-in PSP Web browser worked the best and it didn’t require a ‘moded’ PSP.

airboat

PSP Setup and Limitations

We were using an older PSP-1000 so if you have a newer PSP GO or PSP Vita you may not have the same limitation that we found. However we think if you stick to our ‘worst case’ setup you should be good to go.

Our recommended setup was:

  • Simple Web Pages
  • No Browser Cache
  • Simple Wireless Network

For the PSP-1000 the web pages had to be very simple, no CSS (Cascading Style Sheets) and no advanced HTML tagging. We had hoped to show Node-Red Web pages from the PI but this was not possible.

In our testing we found that it was important to turn off the browser cache, otherwise we found that our commands would only work once. To turn off the PSP browser cache, go into the PSP browser and select “Tools”, then “Settings”, and “Cache Settings”.

cache

Our older PSP-1000 had some problems with the newer WPA2 wireless encryption, so to simplify things we created a small standalone open network. For Arduino projects this isn’t a problem because the Arduino can be made into a standalone access point. On Pi projects where you are using an existing wireless network you might need to do some tweeking to add a guest account.

To add a new connection on the PSP go to the “Network Settings” and select “Infrastructure Mode”. Then select “[New Connection]” and “Scan”. The scan will only show networks that the PSP is able to connect to.

networksettings

A Simple Web Form

An HTML form supports two types of action, a POST and a GET. The GET method is the simpler (but less secure) approach and it passes parameters on the URL command line.

Below is a simple Web form:

<html>
<body>
<h1>Click a button to control the car</h1>
<form action='GO' method='GET' >
<INPUT TYPE='submit' VALUE="GO" >
</form>
<form action='STOP' method='GET' >
<INPUT TYPE="submit" VALUE="STOP" >
</form>
<form action='LEFT' method='GET' >
<INPUT TYPE='submit' VALUE="LEFT" >
</form>
<form action='RIGHT' method='GET' >
<INPUT TYPE="submit" VALUE="RIGHT" >
</form>

</body>
</html>

menu

An Arduino Web Server

To create Arduino WiFi projects the ESP8266 based modules are low cost way to go. There are some good ESP8266 libraries and the examples are fairly easy to follow. The ESP8266 module can be wired into an Arduino Uno/Nano/Mega module or you can by buy boards with the ESP8266 chip integrated in. For our testing we used an older WeMo board, but other options like the NodeMCU, Adafruit HUZZAH or even the Arduino Yún could be used.

The ESP8266WebServer library has a simple standalone access point example. We modified this example (WifiAccessPoint) to include HTML form tags for all our required action.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

int pinleft = 12;
int pinright = 13;
int pinfront = 14;

/* Set these to your desired credentials. */
const char *ssid = "MY8266";
const char *password = "";

char *webpage = "<html><head><title>My8266 Control</title> \
</head><body> \
<h1>Click a button to control the car</h1>

<hr>

\
<form action='/go' method='GET' > \
<input type='submit' style='font-size:150px;color:lime' value='GO'></form>

\
<form action='/stop' method='GET'> \
<input type='submit' style='font-size:150px;color:red' value='STOP'></form>

 \
<form action='/left' method='GET'> \
<input type='submit' style='font-size:150px' value='LEFT'></form>

 \
<form action='/right' method='GET'> \
<input type='submit' style='font-size:150px' value='RIGHT'></form>

 \
</body></html>";

ESP8266WebServer server(80);

/* Just a little test message. Go to http://192.168.4.1 in a web browser
* connected to this access point to see it.
*/
void handleRoot() {
Serial.println("Base page");
server.send(200, "text/html", webpage);
}

void go() {
Serial.println("Go forward");
server.send(200, "text/html", webpage);
digitalWrite(pinleft,LOW);
digitalWrite(pinright,LOW);
digitalWrite(pinfront,LOW);

}
void stop() {
Serial.println("Stop");
server.send(200, "text/html", webpage);
digitalWrite(pinleft,HIGH);
digitalWrite(pinright,HIGH);
digitalWrite(pinfront,HIGH);
}
void left() {
Serial.println("Go left");
server.send(200, "text/html", webpage);
digitalWrite(pinleft,HIGH);
digitalWrite(pinright,LOW);
digitalWrite(pinfront,HIGH);

}
void right() {
Serial.println("Go right");
server.send(200, "text/html", webpage);
digitalWrite(pinleft,LOW);
digitalWrite(pinright,HIGH);
digitalWrite(pinfront,HIGH);
}

void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
pinMode(pinleft,OUTPUT);
pinMode(pinright,OUTPUT);
pinMode(pinfront,OUTPUT);

digitalWrite(pinleft,HIGH);
digitalWrite(pinright,HIGH);
digitalWrite(pinfront,HIGH);

Serial.print("Configuring access point...");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);

IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.on("/", handleRoot);
server.on("/go",go);
server.on("/stop",stop);
server.on("/left",left);
server.on("/right",right);
server.begin();
Serial.println("HTTP server started");
}

void loop() {
server.handleClient();
}

Arduino FM Radio

There are a few FM receiver modules that are available. We used an FM module that is based on the RDA5807M chip and unlike some of the other chips this one supports volume control. To keep our project compact we used the Arduino Nano, but we tested the UNO and Mega and they both worked well.

fmradio

There are a lot of options on how to control your FM radio. We liked the idea of using an old TV remote because this allowed us to change the volume and radio stations anywhere in the room. For this project we used:

• an I2C FM receiver module ($13)
• any Arduino module that has SDA and SCL pins
• an IR receiver ($5)
• a small bread board and some jumpers

The FM receiver module works on the I2C bus that connects to the SDA and SCL pins. Depending on which IR chip you use the wiring will vary slight. The key thing is to connect the data pin correctly. For our example we used pin 11.

circuit2

FM Module

When we first starting working this project there was no Arduino FM library available, so we started to by talking directly with the I2C bus. However now an Arduino FM library is available.

The RDA5807M chip [3] on the FM receiver module has a number of register addresses that we needed to write to. The key ones were:

  • REGISTER 2 – Initialize the chip (0xC003)
  • REGISTER 2 – Enable radio communications (0xC00D)
  • REGISTER 3 – Set the frequency
  • REGISTER 5 – Set the volume

We needed to pause between initializing and enabling radio communications. Setting the radio frequency is done by offsetting the frequency from the minimum range (870) and then splitting the value into high and low bytes.

The volume on register 5 is adjusted between a value of 0, the lowest, and 15 or 0xF the highest. There are other options on register 5 so our code changed the value from 0x84D0 to 0x84DF.

The Arduino modules uses the wire.h library to read and write to I2C devices. To write to a register the important commands are:

  • Wire.beginTransmission
  • Wire.write
  • Wire.endTransmission

An example using these commands would be:


//This is an example of setting the volume to 1
//This sets up communications to a device
Wire.beginTransmission(0x11); // 0x11 is the RDA5807M chip
Wire.write(0x05); // address 0x05 is where you want to write to
Wire.write(0x84); // write 0x84 to the first byte of address 0x05
Wire.write(0xD1); // write 0xD1 to the second byte of address 0x05
Wire.endTransmission(); // finish the write

We made a simple radio test program (Listing 1) that set up the radio to a local frequency at volume 1.


#include <Wire.h>

int freq;
int freqB;
byte freqH, freqL;

void setup()
{
Wire.begin();

// Initialize the RDA5807M chip

Wire.beginTransmission(0x11); // Device address is 0x11
Wire.write(0x02); // Register address 0x02
Wire.write(0xC0); Wire.write(0x03); // Initialize the settings
Wire.endTransmission(); // stop condition
delay(500); // wait 500ms

Wire.beginTransmission(0x11); // Device address is 0x11
Wire.write(0x02); // Register address 0x02
Wire.write(0xC0); Wire.write(0x0D); // Setup the radio for communications
Wire.endTransmission();
delay(500);

// Define an FM station to listen to

freq = 1079; // 107.9 MHz our local FM station
freqB = freq - 870; // chip needs to have freq offset from lowest freq (870)
freqH = freqB>>2; // you need to break the offset freq into 2 parts (hi/low)
freqL = (freqB&3)<<6; // Shift channel selection for matching register 0x03

Wire.beginTransmission(0x11);
Wire.write(0x03);
Wire.write(freqH); // write High freq byte
Wire.write(freqL + 0x10); // write Low freq byte
Wire.endTransmission();

// The volume is from 0-F and its the first bytes, leave all the bytes (0x84D0 - 0x84DF)

Wire.beginTransmission(0x11);
Wire.write(0x05);
Wire.write(0x84); Wire.write(0xD1); // set volume to 1
Wire.endTransmission();
}

void loop()
{

}

Finding TV Remote Codes

We used a small program to find the IR (Infrared) codes from our TV remote. For our program we used the volume up, volume down, channel up and channel down keys. Different TV remotes will have different codes so you will have to find the codes that work with your remote.


/*
IR TEST PROGRAM

PINOUTS:

LEFT = DATA PIN
MIDDLE = GND
RIGHT = 3.3 volts

*/
#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
Serial.println("Setup Complete");
}

void loop()
{
if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value
delay(500);

}
}

ircode

When our IR test program was running we used the Arduino monitor window to show us the different key codes. We manually recorded these codes and used them in our final project.

Using a TV Remote

Our goal was to use a TV remote to change the FM station and to adjust the volume. There are a lot of websites you can use to find nearby radio stations. A good website for this is: http://radio-locator.com.

Our final program  used a number of predefined FM stations that would change with channel up and channel down on the TV remote. The remote’s volume up and down would change the radio’s volume. Remember to change the IR codes to match your TV remote, and the FM stations for your area.


// RDA5807M Radio controlled with a TV Remote
//
#include <Wire.h>
#include <IRremote.h>

int RECV_PIN = 11; //Connect the IR data pin in 11
IRrecv irrecv(RECV_PIN);
decode_results results;

int volume = 0; // start with the volume low
int channellist[]= {999,1029,1021,1079}; // Define some radio stations
int maxc = 4; // Define the number of radio stations used
int channel = 2; // Start with a favorite station

void setup()
{
Wire.begin();

Serial.begin(9600);

irrecv.enableIRIn(); // Start the receiver

radio_init();
setfreq(channellist[channel]);
setvolume(volume);

}
void loop() {
if (irrecv.decode(&results)) {

switch (results.value) {
case 0xE0E0E01F:
Serial.println("vol up");
if (volume < 15) {
volume++;
setvolume(volume);
}
break;
case 0xE0E0D02F:
Serial.println("vol down");
if (volume > 0) {
volume--;
setvolume(volume);
}
break;
case 0xE0E048B7:
Serial.println("chan up");
if (channel < maxc) {
channel++;
setfreq(channellist[channel]);
}
break;
case 0xE0E008F7:
Serial.println("chan down");
if (channel > 0) {
channel--;
setfreq(channellist[channel]);
}
break;
default:
Serial.println(results.value, HEX);
}
irrecv.resume(); // Receive the next value
}
delay(100);
}
//===============================
void setvolume(int thevolume)
{
byte volbyte;

volbyte = thevolume + 0xD0;
Wire.beginTransmission(0x11);
Wire.write(0x05);
Wire.write(0x84); Wire.write(volbyte);
Wire.endTransmission();
delay(500);
}
//===============================
void setfreq(int thefreq)
{
int freqB;
byte freqH, freqL;

freqB = thefreq - 870;
freqH = freqB >> 2;
freqL = (freqB & 3) <<6;

Wire.beginTransmission(0x11);
Wire.write(0x03);
Wire.write(freqH); // write frequency into bits 15:6, set tune bit
Wire.write(freqL + 0x10);
Wire.endTransmission();
delay(500);
}
//================================
void radio_init()
{
Wire.beginTransmission(0x11); // Device address 0x11 (random access)
Wire.write(0x02); // Register address 0x02
Wire.write(0xC0); Wire.write(0x03); // Initialize the settings
Wire.endTransmission();
delay(500); // wait 500ms to finalize setup

Wire.beginTransmission(0x11); // Device address 0x11 (random access)
Wire.write(0x02);
Wire.write(0xC0); Wire.write(0x0D); // Setup radio settings
Wire.endTransmission();
delay(500); // wait 500ms to finalize settings
}

Packaging our Project

We wanted to make our radio project portable, so we came up with two ideas. The first idea was to put all the electronics into a plastic container. For this we used a soap dish ($1) that we drilled three holes in. The first two holes were for the power and speaker cords. The last hole was for the IR receiver. To power our project we used a solar charger ($10), so we could listen to music outside.

soapdish1

Our second idea was to place the electronics inside the pocket of a cooler bag. It is important to have the IR receiver poking out of the pocket.

coolerbag

There are also some fun projects where you could use LCD Keyboard Shields or Touchscreens.

lcd

 

 

Arduino Sailboat

To build the sailboat we used

  • Arduino Uno [1]
  • Prototype shield with bread board ($5)
  • Wireless RF module and remote ($6)
  • Small servo ($6)
  • 6x AA batteries with case and plug
  • K’Nex building pieces
  • 4 plastic bottles
  • 1 small plastic container with a lid
  • String, Duct tape, and a garbage bag (white if you have it)

The boat construction used the 4 bottles for flotation and a K’Nex frame.

structure

Mounting the rudder will probably require some trial and error, our design used some Lego pieces, duct tape and wire to hold it in place.

servo1

For the electronics we had some good success with a wireless RF (Radio Frequency) module. The wireless RF modules are relatively low cost ($6), and they do not require any fancy programming. remote1

wiring

The final Arduino code is :

//
// sailboat1.ino - use a wireless RF motor to move a servo on a sailboat
// RF buttons:
// A = straight (90deg), B = turn left (10deg), C = turn right (10deg)
// Limit rudder turning from 60-120 degrees
//
#include <Servo.h> 
 
Servo myservo; 
int pos;

void setup() {
 pinMode(5, INPUT); // A button - D0 pin on RF module
 pinMode(6, INPUT); // B button - D1 pin on RF module 
 pinMode(7, INPUT); // C button - D2 pin on RF module 
 pinMode(8, INPUT); // D button - D3 pin on RF module 


void loop(){

if (digitalRead(5) == HIGH) { 
 Serial.println("Button A");
 pos = pos + 10;
 if (pos > 120) { pos = 120;} 
 myservo.write(pos); 
 delay(250);
 } 
 if (digitalRead(6) == HIGH) { 
 Serial.println("Button B"); 
 pos = 90;
 myservo.write(pos); 
 delay(250);
 } 
 if (digitalRead(7) == HIGH) { 
 Serial.println("Button C");
 pos = pos - 10;
 if (pos < 60) { pos = 60;} 
 myservo.write(pos); 
 delay(250); 
 } 
 if (digitalRead(8) == HIGH) { 
 Serial.println("Button D"); 
 delay(250);
 }

}

littleBits Remote MP3 Player

For the remote MP3 Player project we used:

  • 1 –  power module with battery
  • 1 – littleBits wireless receiver
  • 1 – littleBits MP3 Player ($50)
  • 1 –  littleBits synth speaker ($20)

We created wireless remote to have a dimmer bit to control the volume and a littleBits button ($8) to change the song.

On the MP3 Player module the mode switch needs to be set to next to enable the remote button switch to change the songs. Finally we connected a speaker wire between the MP3 player and the speaker module and we duct taped the batteries to the bottom of the mounting plates.

littleBits Rover

Create a remote control littleBits rover using the littleBits wireless transmitter (w12) Bit ($40) and the wireless receiver (w11) Bit ($40). These wireless bits can also be  found in some of the littleBits kits, (for example the Gizmo and Gadgets kit).

The wireless modules can pass up to 3 signals. Depending on what you are trying to remotely control you could mix and match between dimmers, buttons and toggle switches. If you add some littleBits proto modules you could come up with some interesting designs.

Step 1 : Build the Remote

To create the wireless remote for the a Rover we needed to control the left and right motors , for this we used the following components:

  •  1- littleBits mounting plate (comes with base set)
  • 1 – littleBits fork module ($12)
  • 2 – littleBits dimmer($8) or slide switches ($10)
  • 1 – littleBits wireless transmitter
  • 1-  littleBits power module with battery ($6)

We connected the power module to a fork module and then the fork module powered our dimmer modules. We mounted all the components on a littleBits mounting plate, and we taped the battery to the back.

frontremote

backremote

The littleBits motor circuit is quite simple, the only important thing is to ensure that you have the wheels turning in the same direction.

motor1.png