14 April 2013

Setup a Raspberry Pi LAMP web server from scratch (without monitor, keyboard or mouse attached)


Friday I received my Raspberry Pi. My intention is to use it as a webserver. When you receive a Raspberry Pi it doesn't do anything straight out of the box. In this blogpost I will give you an overview of how I set up my Raspberry Pi with just:

  • The Raspberry Pi itself
  • A 4GB SD card

So I never connected a screen, keyboard and mouse to it, to install it.

Prepare the SD card

Download the image (I used the Raspbian “wheezy”) and put it to an SD card. To make this process easy I used the Pi filler (for Mac OS X 10.5 through 10.8). Read more on how to set up your SD card here.

SSH to your Pi

Insert your prepared SD-card in your Raspberry Pi, connect your ethernet and hook it up to power. Your Raspberry Pi will boot.

Since the latest images SSH is enabled by default. This makes it possible to directly connect to your Raspberry Pi, without attaching a monitor, keyboard and mouse the first time.

You can find the IP-address of your Raspberry Pi in your router, or use a tool like Pi Finder.

If you open a terminal (e.g. Terminal on Mac) you can connect to your Raspberry Pi:
ssh pi@192.168.xxx.xxx
The default password is "raspberry".
But to make life easier, you can copy your SSH certificate to the Raspberry Pi to make logging in very easy:
cat ~/.ssh/id_rsa.pub | ssh pi@192.168.xxx.xxx 'cat >> ~/.ssh/authorized_keys'
Just type the password one last time and you're done!
After logging in,  you can change the default password:
sudo passwd pi <<<PASSWORD>>>

Basic Raspberry Pi config

Run the following, to configure your Raspberry Pi:
sudo raspi-config
raspi-config

I made the following settings:
  • Expand_rootfs, to have more storage space (makes it possible to use the full SD card)
  • memory_split, changed it to 16, because I don't need graphical memory for my webserver. 
  • boot_behaviour, "no", don't start the desktop
  • update, to update raspi-config

Update Debian

To update Debian:
  • sudo dpkg-reconfigure tzdata
  • sudo apt-get update
  • sudo apt-get upgrade

Install Git

sudo apt-get install git-core

Install automatic firmware updater and update

  • sudo wget https://raw.github.com/Hexxeh/rpi-update/master/rpi-update -O /usr/bin/rpi-update && sudo chmod +x /usr/bin/rpi-update
  • sudo rpi-update
Now the firmware and software are up to date, reboot the Pi:
sudo shutdown -r now

Install Apache and PHP5

sudo apt-get install apache2 php5 libapache2-mod-php5
If you want to enable all error reporting you could do stuff like this:
  • echo 'error_reporting  =  E_ALL' > /etc/php5/conf.d/error_reporting.ini
  • echo 'display_errors = On' >> /etc/php5/cond./error_reporting.ini

Install MySQL

sudo apt-get install mysql-server mysql-client php5-mysql

Restart Apache

sudo service apache2 restart

That's it!

Now you have a running webserver with PHP5 and MySQL. You can put your PHP files in /var/www/.

09 April 2013

Arduino Facebook like-counter with 7 segment display

Last year I wanted to be able to follow the amount of likes on a website, but not by looking at a Facebook or the website itself. I made an IRL display with the amount of likes with an Arduino.

The case
I created an PHP-script, using the Facebook API, checking the amount of likes and just outputting it. My Arduino would regularly check for the value outputted by my PHP script and display this on its display.

Requirements
The stuff I used is:


Result
Check this video for the results:

My Arduino code looks like this:

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
char serverName[] = "xxxxxxxx.nl"; //location of PHP script telling me the amount of likes

const int latchPin = 8;
const int clockPin = 3;
const int dataPin = 9;
byte chars[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xf7,0xfb,0xab,0x86}; //0-9," ", -, _,i,n,e

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  
  //Put "ini" on the dis
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[13]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[14]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[13]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
  shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
  digitalWrite(latchPin, HIGH);
  
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    //Put "e" (error) on the dis
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[15]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    digitalWrite(latchPin, HIGH);
    // no point in carrying on, so do nothing forevermore:
    while(true);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
}

void loop()
{
  checkOnlineStatus();
  delay(2000);
}

void checkOnlineStatus()
{
  //Serial.println("connecting...");
  boolean newLine = true;
  String line = "";
  
  if (client.connect(serverName, 80)) {
    //Serial.println("connected");
    // Make a HTTP request:
    client.println("GET / HTTP/1.0");
    client.println("Host: rogier.nu");
    client.println();
  }
  
while(client.available()){
    char c = client.read();
    //Serial.print(c);
    
    // if you've gotten to the end of the line (received a newline
    // character) and the line is blank, the http request has ended,
    // so you can send a reply
    if (c == '\n' && newLine) {
      
    }
    if (c == '\n') {
      // you're starting a new line
      newLine = true;
      line = "";
    } 
    else if (c != '\r') {
      // you've gotten a character on the current line
      newLine = false;
      line += c; 
    }
  }
  

  processLine(line);

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    client.stop();
  }
}

void processLine(String line)
{
  if(line.length() > 0) {
    //Serial.println("Verwerken:" + line);

    digitalWrite(latchPin, LOW);

    //Putting up the online value
    for(int i=line.length()-1; i >= 0; i--)
    {
      int bitToSet = (byte)line.charAt(i) - 48;
      shiftOut(dataPin, clockPin, MSBFIRST, chars[bitToSet]);
    }
    
    //Putting up the leading zeroes
    for(int i=0; i<8-line.length(); i++)
    {
      shiftOut(dataPin, clockPin, MSBFIRST, chars[10]);
    }
    
    digitalWrite(latchPin, HIGH);
  }
 }
Improvements
My sketch is relying on an external PHP-script, to make the Arduino code as simple as possible. A better way to do this is by having the Arduino make direct connections to Facebook, as is done in this project: Facebook Like box