Raspberry Pi Temperature Sensor Web Server – Part 3 (Scheduling temperature readings and PHP script) — May 18, 2015

Raspberry Pi Temperature Sensor Web Server – Part 3 (Scheduling temperature readings and PHP script)

Now wouldn’t it be nice to have our python script work autonomously, putting a temperature reading into the database every 5 minutes. To do this we will use Crontab, which is a handy unix tool to schedule jobs. A good explanation of what crontab is can be found here.

To open Crontab enter the following in your terminal.

crontab -e

Inside the Crontab file enter the following at the bottom. This simply runs our Python script every 5 minutes. If you have used different file and folder names, adjust them accordingly.

*/5 * * * * /home/pi/tempLog/readTempSQL.py

At its current state this will not work though because the readTempSQL.py script isn’t yet executable so the Cronjob will fail. To make the Python script executable, firstly enter the following at the top of the readTempSQL.py file.

#!/usr/bin/env python

This is a ‘shebang’ line, which Wikipedia will tell you “In computing, a shebang (also called a hashbang, hashpling, pound bang, or crunchbang) refers to the characters “#!” when they are the first two characters in an interpreter directive as the first line of a text file. In a Unix-like operating system, the program loader takes the presence of these two characters as an indication that the file is a script, and tries to execute that script using the interpreter specified by the rest of the first line in the file.”

Now we just need to change the file permission to executable.

sudo chmod +x readTempSQL.py

To test that the file is now executable, navigate to your tempLog directory and enter

./readTempSQL.py

The script should run and print an output to the terminal window. Congratulations the file is now executable. Check your database after 10 minutes or so to make sure your Cronjob is working as when the script is run by Crontab the output is not displayed in the terminal window.

Now lets make a php script to return our database data. Change directory to /var/www
and make a new file called temperaturejson.php.

sudo nano temperaturejson.php

Enter the following into that new file.

<?php
 
$username="root";
$password="password";
$database="temp_database";
 
mysql_connect(localhost,$username,$password);
@mysql_select_db($database) or die( "Unable to select database");
 
$query="SELECT * FROM tempLog";
$result=mysql_query($query);
 
$num=mysql_numrows($result);
 
mysql_close();
 
$tempValues = array();
 
$i=0;
while ($i < $num)
{
        $dateAndTemps = array();
        $datetime = mysql_result($result,$i,"datetime");
        $temp = mysql_result($result,$i,"temperature");
 
        $dateAndTemps["Date"] = $datetime;
        $dateAndTemps["Temp"] = $temp;
 
        $tempValues[$i]=$dateAndTemps;
        $i++;
}
 
echo json_encode($tempValues);
 
?>

This new php script gets the data from our database and then loops through the results putting them into an array where the key is either “Date” or “Temp” and the corresponding object is the result from the database.You don’t really need to give the objects keys but I think it makes it much easier when getting the data into the app. These arrays are then added to a larger array holding each reading of Date and Temp, which is then encoded into json and output using echo.

Now test this out. Using any browser go to the following address (substituting my IP for yours of course!). If you don’t get the desired output firstly check you can get to the test page on the Raspberry Pi. If you can try changing the echo to just output a string to test the page. Then check your database to make sure you actually have data to display.

http://192.168.0.11/temperaturejson.php

If all has worked correctly you will get an output similar to this

[{“Date”:”2014-12-28 17:26:20″,”Temp”:”18.90″},{“Date”:”2014-12-28 17:27:05″,”Temp”:”18.90″},{“Date”:”2014-12-28 17:27:52″,”Temp”:”18.90″},{“Date”:”2014-12-28 17:30:39″,”Temp”:”19.00″},{“Date”:”2014-12-28 17:31:02″,”Temp”:”18.90″},{“Date”:”2015-01-04 22:29:24″,”Temp”:”18.60″},{“Date”:”2015-05-14 20:56:07″,”Temp”:”21.80″},{“Date”:”2015-05-17 19:55:05″,”Temp”:”22.90″},{“Date”:”2015-05-17 19:56:17″,”Temp”:”22.90″},{“Date”:”2015-05-17 20:06:18″,”Temp”:”23.00″},{“Date”:”2015-05-17 20:47:03″,”Temp”:”23.20″}]

That is a wrap for the Raspberry Pi stuff. Now we move on to making an iOS app to do something with our data.

Advertisements
Centre UICollectionView Cells Horizontally iOS — May 5, 2015

Centre UICollectionView Cells Horizontally iOS

Or Centre UICollectionView Cells Horizontally iOS for US dudes.

I had to do this for a project recently so thought I would share.

Create a single view project in Objective C and open the Storyboard. For ease of this example turn Auto Layout and Size Classes off using the iPad size for the view. This can be done in File Inspector View on the right.

Screen Shot 2015-04-28 at 21.44.02

In the general settings under Deployment info, un-tick the boxes for portrait and upside down so the app can only be displayed horizontally.

Next, setup the View Controller simulated metrics in the Attribute Inspector as follows.

Screen Shot 2015-04-28 at 21.44.25

Add a UICollectionView to the ViewController and make it 1000 in width and 300 in height. Try to centre it in the middle of the View.

Screen Shot 2015-04-28 at 21.47.50

 

Change the scroll direction to horizontal in the Attribute Inspector for the UICollectionView. Make sure items is set to 1 while you are there so that a prototype cell stays in the collection.

Screen Shot 2015-04-28 at 21.58.06

Now make the CollectionViewCell 200 in width and 250 in height

Screen Shot 2015-04-28 at 21.50.14

I would now add some views and labels to the default prototype cell so that what you are working with is realistic. Here is my collection View and cell.

Screen Shot 2015-04-28 at 22.01.40

With the UICollectionView selected, go into Connections Inspector and connect the Delegate to the View Controller.

Screen Shot 2015-04-28 at 22.04.38

We need to implement the UICollectionViewDelegate. Add this to the ViewController.h

 

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UICollectionViewDelegate>

@end

Now we will add two methods from the UICollectionViewDelegate. These methods will simply tell the UICollectionView how many collection cells we’re displaying and what cells to display. Pretty much the same as a tableView Delegate.

#import "ViewController.h"

@implementation ViewController
{
	NSInteger _numberOfCells;
}

- (void)viewDidLoad
{
	[super viewDidLoad];
	_numberOfCells = 3;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{

	return _numberOfCells;
}

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

	UICollectionViewCell *cell = (UICollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

	return cell;
}

Now build and run the project. You should see something similar to the below. If not, put a breakpoint in the delegate methods and make sure they are called and the delegate is setup correctly.

Screen Shot 2015-05-04 at 20.16.07

Now lets add another method to centre the 3 UICollectionViewCells. You will notice I have hardcoded in all of the width values but that is just to make this more understandable, it should be quite simple to get the values at run time programmatically. So you should now adapt your ViewController to look like the below.

#import "ViewController.h"

#define CELL_WIDTH 200
#define CELL_SPACING 10
#define COLLECTIONVIEW_WIDTH 1000

@implementation ViewController
{
	NSInteger _numberOfCells;
}

- (void)viewDidLoad
{
	[super viewDidLoad];
	_numberOfCells = 3;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{

	return _numberOfCells;
}

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

	UICollectionViewCell *cell = (UICollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

	return cell;
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
	NSInteger viewWidth = COLLECTIONVIEW_WIDTH;
	NSInteger totalCellWidth = CELL_WIDTH * _numberOfCells;
	NSInteger totalSpacingWidth = CELL_SPACING * (_numberOfCells -1);

	NSInteger leftInset = (viewWidth - (totalCellWidth + totalSpacingWidth)) / 2;
	NSInteger rightInset = leftInset;

	return UIEdgeInsetsMake(0, leftInset, 0, rightInset);
}

@end

There is no reason to use that many lines of code or to have both a left and right inset other than simplicity for this demonstration. That method can be reduced to a few lines at most. Run the project again and you should have a centred UICollectionView like below.

Screen Shot 2015-05-05 at 20.26.22

Send/Recieve Hex Over Bluetooth SPP from Android — March 29, 2015

Send/Recieve Hex Over Bluetooth SPP from Android

If you have used any of my earlier blog posts for sending data to a bluetooth module from an Android device you may have noticed you can only send ASCII characters. This is fine for most activities but what if you need to send carriage return or line feed, which are 0xD and 0xA respectively.

Simply add a new method to send an int, which represents the hexadecimal you wish to send.


 public void writeHex(int i){
        	try{
				mmOutStream.write(i);
        		}catch (IOException e){   
        			finish();
                	Toast.makeText(getBaseContext(), "DEVICE UNAVAILABLE", Toast.LENGTH_SHORT).show();
        	}
        }

Do what you want in the catch statement, I have lazily told my activity to finish if an exception is raised.

To use this new method just call it like I have below. In this example I am using it to send the line feed command (0xA).

mConnectedThread.writeHex(0xA);

mConnectedThread is just the name of the thread I am using to handle my bluetooth methods. Notice you have to write 0x before the hexadecimal value, simply writing A would not work.

 

Now say you have received a load of ASCII via bluetooth but for some reason you want to display it as hexadecimals. I found the best way to do this is to add a string conversion method.

  private String convertStringToHex(String string)
  {
	  StringBuilder newString = new StringBuilder();
	  for (int i=0; i<string.length(); i++)
	  {
		  newString.append(String.format("%x ", (byte)(string.charAt(i))));
	  }
	  return newString.toString();
  }

Simply pass in your string of ASCII characters and the returned string will be in hex. I wanted spaces between my values so I put a space after %x but if you prefer it without just remove it.

 

 

Raspberry Pi Temperature Sensor Web Server – Part 2 (Setting up and writing to a MySQL Database) — January 5, 2015

Raspberry Pi Temperature Sensor Web Server – Part 2 (Setting up and writing to a MySQL Database)

To store our temperature values we will need a database, we will use MySQL for this. To access the database online we will need a web server and a script to run on it, Apache and PHP respectively.

To install Apache and PHP on the raspberry pi enter this command, when prompted type y.

sudo apt-get install apache2 php5 libapache2-mod-php5

Once complete you can test the web server by simply entering the IP address of the Pi into a web browser of a device that is on the same local network as the Pi. You will get the following page if successful:

Screen Shot 2014-12-28 at 14.17.49

Now install MySQL by entering the following, press y again when prompted.

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

A prompt will pop up asking you to enter a password for the MySQL database. Make sure you remember it/write it down!!!

We will also be editing our MySQL database from our Python script in the future so download the corresponding Python library:

sudo apt-get install python-mysqldb

Now open MySQL:

sudo mysql –u –p

This logs us in to MySQL as the root user (-u) and it will prompt for a password (-p) on entry.

Enter the password you created earlier.

We are now going to create a database, I called mine temp_database which is a bit unimaginative. Here is a cheat sheet of MySQL commands too.

CREATE DATABASE temp_database;

We can check this has worked by entering the below. A list of the databases currently held by MySQL will be displayed. Don’t be alarmed if there is more than the one you just created.

SHOW DATABASES;

+——————–+
| Database           |
+——————–+
| information_schema |
| mysql             |
| performance_schema |
| temp_database     |
+——————–+
4 rows in set (0.00 sec)

Now we want to make a new table in the temp_database. To this we firstly have to tell MySQL that we wish to use the temp_database:

USE temp_database;

We now create a table in MySQL using the following commands. MySQL commands are out of the scope of this blog but essentially we are making a table called tempLog that has two fields; datetime (of type DATETIME) and temperature(of type FLOAT). Both must have values (i.e. not null).

CREATE TABLE tempLog(datetime DATETIME NOT NULL, temperature FLOAT(5,2) NOT NULL);

To check that our table is correct we can check by entering the following:

mysql> DESCRIBE tempLog;

You will get the following output, describing the table’s fields.

+————-+————+——+—–+———+——-+
| Field       | Type       | Null | Key | Default | Extra |
+————-+————+——+—–+———+——-+
| datetime   | datetime   | NO   |     | NULL   |       |
| temperature | float(5,2) | NO   |     | NULL   |       |
+————-+————+——+—–+———+——-+

Exit MySQL by pressing ctrl+z. Now go to your tempLog directory and add another Python script in nano called readTempSQL.py

cd tempLog

sudo nano readTempSQL.py

Copy the following code into your new Python script.

import os
import time
import datetime
import glob
import MySQLdb
from time import strftime

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
temp_sensor = '/sys/bus/w1/devices/28-00000622fd44/w1_slave'

# Variables for MySQL
db = MySQLdb.connect(host="localhost", user="root",passwd="password", db="temp_database")
cur = db.cursor()

def tempRead():
    t = open(temp_sensor, 'r')
    lines = t.readlines()
    t.close()

    temp_output = lines[1].find('t=')
    if temp_output != -1:
        temp_string = lines[1].strip()[temp_output+2:]
        temp_c = float(temp_string)/1000.0
    return round(temp_c,1)

while True:
    temp = tempRead()
    print temp
    datetimeWrite = (time.strftime("%Y-%m-%d ") + time.strftime("%H:%M:%S"))
    print datetimeWrite
    sql = ("""INSERT INTO tempLog (datetime,temperature) VALUES (%s,%s)""",(datetimeWrite,temp))
    try:
        print "Writing to database..."
        # Execute the SQL command
        cur.execute(*sql)
        # Commit your changes in the database
        db.commit()
        print "Write Complete"

    except:
        # Rollback in case there is any error
        db.rollback()
        print "Failed writing to database"

    cur.close()
    db.close()
    break

This is a modification of our original Python script but we are adding code to handle the MySQL functionality. Firstly, at the top of the script we add an import for the MySQLdb Python library we downloaded earlier. A bit further down you will see variables that will be used when communicating with MySQL (password, user, host etc) – remember to change them to your variables!

“sql = …” is a string that we will send to MySQL as a command that adds our datetime and temperature values to the tempLog database. There is then a try statement that executes the sql command. If for some reason that fails the except code will run, printing a fail message and discarding attempted changes to the database. Play about with this code and try to change stuff, its the only way I learnt how to it works.

Now run the Python script we just made a few times.

sudo python readTempSQL.py

You should see the following output on your terminal window if all has worked:

pi@raspberrypi ~/tempLog $ sudo python readTempSQL.py
18.6
2015-01-04 22:29:24
Writing to database…
Write Complete

 

Now lets check that the Python script actually entered data into the MySQL database. Log back into MySQL and USE the temp_database. We can then query the tempLog table:

mysql -u root -p

USE temp_database;

mysql> SELECT * FROM tempLog;

In the terminal window you will see the following output.

+———————+————-+

| datetime           | temperature |
+———————+————-+
| 2014-12-28 17:26:20 |       18.90 |
| 2014-12-28 17:27:05 |       18.90 |
| 2014-12-28 17:27:52 |       18.90 |
| 2014-12-28 17:30:39 |       19.00 |
| 2014-12-28 17:31:02 |       18.90 |
+———————+————-+
5 rows in set (0.00 sec)

If all has worked, well done! Next we will look at getting the data from the database for our app.

 

Raspberry Pi Temperature Sensor Web Server – Part 1 (Intro, sensor setup and Python script) — December 24, 2014

Raspberry Pi Temperature Sensor Web Server – Part 1 (Intro, sensor setup and Python script)


INTRO
To be honest I only wanted a Raspberry Pi to act as simple web server so that I could practice network communication with my iOS apps. However, I soon learnt that they are a lot of fun and got very side tracked. I decided to make a temperature sensor that my app could communicate with using a web server. There are lots of tutorials that I used to make this happen but hopefully this will show every part in detail so its easy to understand. I will cover:

1 – Setting up the Maxim DS18B20+ temperature sensor and writing a Python script to read the sensor
2 – Setup of LAMP. Linux, Apache, MySQL & PHP for the webserver + Writing the values from the temp sensor to the MySQL database
3 – Writing PHP scripts to access the MySQL database from a web browser
4 – Outputting the results as JSON for a mobile app to read.
5 – An simple iOS app to read our temp sensor values and display them

All of the source code can be found in my Github Repo.

There are no prerequisites to this other than knowing how to install Raspbian onto a Raspberry Pi and using SSH to access the Pi over your home network (I’m using Terminal on mac but Putty on windows will work fine). It isn’t necessary to SSH but I prefer to use it. This guide will work perfectly well with a Pi setup with a monitor and keyboard.


WIRING UP

So as promised lets set up our Pi for the temperature sensor and write a Python script to read the temperature from it. We will use GPIO pin 4 as it is the default Pi pin for 1-wire comms, which the temperature sensor uses to communicate. All comms are sent via this wire to our Pi in the form of a unique serial number for the sensor and a temperature reading. Because of this unique serial number we can even have more than one device on the same GPIO but one step at a time.

Set up your Pi and DS18B20+ as below. The wiring is fairly simple, just a 3.3V supply voltage, ground and data. There is a 10K pull up resistor from Vdd to data just so the pin isn’t floating.

Screen Shot 2014-12-21 at 16.57.05
Wiring diagram

Heres mine:

IMG_2808
Temperature Sensor wired up!

READING THE TEMPERATURE SENSOR

Put a fresh install of Raspbian onto your Pi, connect it to your local network via the Ethernet cable and turn it on. Now SSH into your Pi using Terminal and enter the password.

***If for some reason when attempting to access the Pi via SSH after booting up your Pi with a fresh Raspbian install you get an RSA key warning just type this into your terminal to delete all stored RSA tokens. ***

rm -f ~/.ssh/known_hosts

We need to load the drivers for the 1-wire comms and the temp sensor into the Pi kernel. Modprobe is a Linux program to add a loadable kernel into the Linux kernel. In your terminal enter:

sudo modprobe w1-gpio

sudo modprobe w1-therm

Now change your working directory (cd) to:

cd /sys/bus/w1/devices/

This is where the devices running on the 1-wire will be. So to find our newly created device just list the contents of the directory with ls.

ls

Now you should see something listed like

28-00000622fd44 w1_bus_master1

This is the serial number for the device. To interrogate that device we need to go into its directory. Make sure you use the serial number of your own sensor!!

cd 28-00000622fd44

The sensor writes to a file called w1_slave so if we just read that file we can now finally know what temperature it is. Enter:

cat w1_slave

cat simply displays the contents of a file. BTW this documentation may come in handy if some of these commands are new.

You will get the following output:

0b 01 4b 46 7f ff 05 10 a8 : crc=a8 YES
0b 01 4b 46 7f ff 05 10 a8 t=16687

The second line shows the temp “t = xxxxx” in degrees Celsius. This may seem high but that’s because you need to format the data, as the value for t is the temperature to 3dp. So read it as t = xx.xxx . For example 16.687. Yes it is cold in here!

Now this is great and all but it’s a bit on the laborious side so lets write a Python script to do all of the hard work for us.


WRITING A PYTHON SCRIPT TO GET THE TEMPERATURE

Go back to the root directory and make a new directory (mkdir) called tempLog.

cd

mkdir tempLog

Go into the new directory and create a new python file in nano.

cd tempLog

sudo nano getTemp.py

Copy the code below taking care to use your own value for the sensor. Explanation beneath the code.

import os
import time
import datetime
import glob
from time import strftime

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
temp_sensor = '/sys/bus/w1/devices/28-00000622fd44/w1_slave'

def tempRead():
        t = open(temp_sensor, 'r')
        lines = t.readlines()
        t.close()

        temp_output = lines[1].find('t=')
        if temp_output != -1:
                temp_string = lines[1].strip()[temp_output+2:]
                temp_c = float(temp_string)/1000.0
        return round(temp_c,1)

while True:
    temp = tempRead()
    print temp
    datetimeWrite = (time.strftime("%Y-%m-%d ") + time.strftime("%H:%M:%S"))
    print datetimeWrite
    break

We first import all of the Python libraries we need. We then load the gpio and therm kernels again using modprobe. Rather than write it out again and again we also use a variable to store our path to the sensor’s w1_slave file, I called it temp_sensor.

A method called tempRead is defined. In this method we read in the w1_slave file using open ‘r’. The file is then converted in to an array of strings called ‘lines’ using readlines.

If you remember it is the second line of the w1_slave file that contains the temperature so we search lines[1] using find for “t=”. Which will give us an index value of where that string occurs. If the returned value from that find is not -1(which means it didn’t find it) we then strip out the temperature reading as a string from the index where “t=” was +2 to the end of the line. If you didn’t +2 you would get “t=xxxxx” as the temperature, we want “xxxxx”.

Then the string is converted to a float, divided by 1000 to put the temperature into proper format of xx.xxx and then returned to the while loop.

When the script is run the first thing it does is go to the while loop. Here it will call our previously defined method tempRead to get the value of the sensor. It will then print the value to the output. Then just to make things look a bit nicer it gets the current date and time and prints it out on the output one line below. Break then stops the while loop and ends the script. I used a while loop so that if you wish you can remove break and insert time.sleep(10) for example so that the temperature and current date and time is output every 10 seconds.

Hopefully that all makes sense. Close the nano file by pressing ctrl and x. It will prompt you to save, press y to confirm writing and the filename.

Now lets give it a go. While still in the tempLog directory enter:

sudo python readTemp.py

You will get something like this:

pi@raspberrypi ~/tempLog $ sudo python readTemp.py
16.4
2014-12-24 11:51:08

We now have the basic workings of our temperature sensor and logger setup. In part 2 we will set up the web server and MySQL table for our data.

RFduino & iOS – Sending large strings — September 1, 2014

RFduino & iOS – Sending large strings

I have been playing with the RFduino and IOS again. One small limitation of the RFduino is that it can only send 20 bytes of data at a time .

In this post I will show you a little sketch and iOS app I made to send long strings to an RFduino and display them on an LCD display. By the end you will have something like the below:

DSC_0004
A complete setup (and my leg)

 

*** A free version off the finished app is available from the Apple App Store here.

RFduino Setup

If you have never set up and RFduino read this first.

Grab your RFduino, breadboard, LCD screen and potentiometer. Connect them as shown below. Although the diagram shows a 2×16 display I used a 4×20 LCD screen (couldn’t find 4×20 on Fritzing!) but this will work with a 2×16 with some minor adjustments to the Arduino sketch.

* LCD RS pin to RFduino pin 5
* LCD Enable pin to RFduino pin 4
* LCD D4 pin to RFduino pin 3
* LCD D5 pin to RFduino pin 2
* LCD D6 pin to RFduino pin 1
* LCD D7 pin to RFduino pin 0
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

Screen Shot 2014-08-30 at 11.05.58
RFduino circuit diagram

 

The Arduino sketch uses the RFduino library so the BLE hard work is already done for us. Although everything in this example is quite simple there is a fair bit of code because I have implemented the following to make it a bit more interesting: auto one line scrolling text, RSSI signal strength and meter, and a temperature display. I have tried to keep it all separate in the code and have commented on how it all works but if you have any questions post a comment.

The most important part of the Arduino code is the section where the data is received from the BLE connection and how it is all put together in one string. The simplest way I could think of doing this was to put an identifier character at the beginning of every string I sent to the RFduino. When the RFduino receives data it checks the first character (data[0]) and if it is a ‘1’ is knows the following characters in data[] are the first part of the incoming string. If the first character is a ‘2’ it will know the following characters in data[] are be appended to the string of already received characters.

void RFduinoBLE_onReceive(char *data, int len)
{
  String inputString = "";
   if (data[0] == '1'){
     //First packet
     for (int i = 1; i < len; i++) {
      inputString += data[i];
      }
      scrollText = "";
      stringStart = stringStop = 0;
      scrollCursor = screenWidth;
      scrollText += inputString;
    }

    if (data[0] == '2'){
      //adds any packet after to the string as it is identified with '2'
     for (int i = 1; i < len; i++) {
      inputString += data[i];
      }
      scrollText += inputString;
    }
}

As we can only send 12 characters over the standard RFduino setup this method reduces this to 11 characters, as the first character is now the identifier. For example if I wanted to send “Hello world how are you today?” it would be sent like this:

1Hello world

2 how are to

2day?

We are relying solely on the fact that the BLE connection does not miss any transmissions but so far in my testing this method has never failed.

Of course you can also add more check conditions for data[0] which when activated will do other functions. For example, in my full code you will see that when a ‘0’ is received the RFduino resets its display string to the default message that it displays after setup.

Here is the full Arduino code

#include <RFduinoBLE.h>
#include <LiquidCrystal.h>

//scrolling - modified version of http://nishantarora.in/tutorial-arduino-16x2-lcd-how-to-scroll-only-one-line-at-a-time-while-keeping-the-other-constant.naml
LiquidCrystal lcd(5, 4, 3, 2, 1, 0);
int screenWidth = 20;
int screenHeight = 4;
int stringStart, stringStop = 0;
int scrollCursor = screenWidth;
//default screen Text
String scrollText = "No messages today :(";

//signal params
int signalLevel = 0;
bool showSignal = false;

//custom graphics for LCD
byte sigHigh[8] = {
  B00001,
  B00001,
  B00001,
  B00101,
  B00101,
  B10101,
  B10101,
};
byte sigMedium[8] = {
  B00000,
  B00000,
  B00000,
  B00100,
  B00100,
  B10100,
  B10100,
};

byte sigLow[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B10000,
  B10000,
};

void setup()
{
  //create custom characters for LCD
  lcd.createChar(0, sigHigh);
  lcd.createChar(1, sigMedium);
  lcd.createChar(2, sigLow);

  lcd.begin(screenWidth,screenHeight);
  lcd.print(scrollText);

  //RFDuino setup
  RFduinoBLE.deviceName = "Display";
  RFduinoBLE.advertisementData = "data";
  RFduinoBLE.advertisementInterval = MILLISECONDS(300);
  RFduinoBLE.txPowerLevel = -20;  // (-20dbM to +4 dBm)

  // start the BLE stack
  RFduinoBLE.begin();
}

void loop()
{
  //Scrollig display*******************
  lcd.setCursor(0,0);
  lcd.print("                    ");
  lcd.setCursor(scrollCursor, 0);
  lcd.print(scrollText.substring(stringStart,stringStop));

  if(stringStart == 0 && scrollCursor > 0){
    scrollCursor--;
    stringStop++;
  } else if ((stringStart == stringStop) || (stringStart == scrollText.length())){
    stringStart = stringStop = 0;
    scrollCursor = screenWidth;
  } else if (stringStop == scrollText.length() && scrollCursor == 0) {
    stringStart++;
  } else {
    stringStart++;
    stringStop++;
  }
  //***********************************

  RFduino_ULPDelay( SECONDS(0.3) ); //delay 

  //temperature************************
  float temp = RFduino_temperature(CELSIUS);
  temp-=6.5;      //calibrattion for room temperature(ish!!!)
  lcd.setCursor(0, 3);
  lcd.print(temp);
  lcd.print((char)223); //degrees symbol
  lcd.print("C");
  //**********************************

  //Signal level**********************
  if (showSignal == true){
    lcd.setCursor(14,3);
    lcd.print(signalLevel);
    lcd.print("dBm");

    lcd.setCursor(13,2);
    lcd.print("RxPWR ");

//for graphic representation of signal
    if (signalLevel >= -60){
       lcd.write(byte(0));
    }
    if ((signalLevel < -60) && (signalLevel >= -75)){
       lcd.write(byte(1));
    }
    if (signalLevel < -75){
       lcd.write(byte(2));
    }
  }
  //**********************************
}

void RFduinoBLE_onConnect()
{
  lcd.setCursor(0,1);
  lcd.print("____________________");  //clears one line of screen
  lcd.setCursor(0, 2);
  lcd.print("*Connected*");
  showSignal = true;
}

void RFduinoBLE_onDisconnect()
{
  lcd.setCursor(0,2);
  lcd.print("Device Disconnected!");
  showSignal = false;
  delay(2000);
  lcd.setCursor(0,2);
  lcd.print("                    ");
  lcd.setCursor(0,1);
  lcd.print("                    ");
  lcd.setCursor(14,3);
  lcd.print("      ");
}

// returns the dBm signal strength indicated by the receiver after connection (-0dBm to -127dBm)
void RFduinoBLE_onRSSI(int rssi)
{
  signalLevel = rssi;
}

void RFduinoBLE_onReceive(char *data, int len)
{
  String inputString = "";
    if (data[0] == '0'){
      //clears all data
      scrollText = "No message today :(";
      stringStart = stringStop = 0;
      scrollCursor = screenWidth;
    }
   if (data[0] == '1'){
     //First packet
     for (int i = 1; i < len; i++) {
      inputString += data[i];
      }
      scrollText = "";
      stringStart = stringStop = 0;
      scrollCursor = screenWidth;
      scrollText += inputString;
    }

    if (data[0] == '2'){
      //adds any packet after to the string as it is identified with '2'
     for (int i = 1; i < len; i++) {
      inputString += data[i];
      }
      scrollText += inputString;
    }
}

Load up the sketch on your RFduino and turn it on. If all has worked correctly you should be greeted by the following screen and if you have a standard RFduino app on your phone you should see “Display” come up when you search for devices.

DSC_0006
All systems go

 

iOS Application

RFduino have been kind enough to produce a bare bones iOS framework that we can use to get our app started. However, there a few setup steps required before it will work correctly.

This is an adaption of Arnaud Boudou’s setup instructions, which go into much greater detail and are very good. 

1. Download the zip from GitHub here. You need the following folder:

RFduino/iPhone Apps/RFduino

Make a new iPhone project with a single view. Drag the RFduino folder from the above file path and make sure you copy the files and add to the project target.

Screen Shot 2014-08-31 at 20.29.03
Copy the RFDuino folder into your project…


2. Delete your original AppDelegate.h and AppDelegate.m files. Don’t worry there are replacement AppDelegate files in the imported RFduino folder that will take over the role of AppDelegate.

3. In the ScanViewController.m file replace didLoadServiceRFduino function with the code below.

- (void)didLoadServiceRFduino:(RFduino *)rfduino
{
    UIStoryboard *storybord = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    AppViewController *viewController =[storybord instantiateInitialViewController];

    viewController.rfduino = rfduino;

    loadService = true;
    [[self navigationController] pushViewController:viewController animated:YES];
}

4. In the ScanViewController.m file replace all occurrences of AppViewController with ViewController.

5. Add the CoreBluetooth framework to your project. Project Page>Build Phases tab>Link Binary with Libraries>Add CoreBluetooth

6. Open ViewController.h and replace the contents with the following code. This adds a property for rfduino and sets the ViewController as a delegate of RFduinoDelegate.

#import <UIKit/UIKit.h>
#import "RFduinoDelegate.h"
#import "RFduino.h"

@interface ViewController : UIViewController<RFduinoDelegate>

@property(nonatomic, strong) RFduino *rfduino;

@end

7. Open ViewController.m and add a @synthesize for the rfduino property.

Run the app with the RFduino on and you should see that the RFduino is displayed in the list.

IMG_2190
A familiar view hopefully…

If you select the displayed RFduino, the app will open a new blank view. Time to change that!

Open Main.storyboard. Add two buttons (“Clear All”, “Disconnect”), two labels (“Connected to:”, default) and a text field. Arrange them as below.

Screen Shot 2014-08-31 at 22.31.02

I also decided to add a gradient background to make things look a bit more interesting. If you want to do this add a new objective C class called Background Gradient and fill in the .h and .m files as below.

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>

@interface BackgroundGradient : NSObject

+(CAGradientLayer*) blueGradient;

@end
#import "BackgroundGradient.h"

@implementation BackgroundGradient

//Blue gradient background
+ (CAGradientLayer*) blueGradient {

    UIColor *colorOne = [UIColor colorWithRed:(247/255.0) green:(157/255.0) blue:(40/255.0) alpha:1.0];
    UIColor *colorTwo = [UIColor colorWithRed:(245/255.0)  green:(60/255.0)  blue:(55/255.0)  alpha:1.0];

    NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, nil];
    NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
    NSNumber *stopTwo = [NSNumber numberWithFloat:1.0];

    NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];

    CAGradientLayer *headerLayer = [CAGradientLayer layer];
    headerLayer.colors = colors;
    headerLayer.locations = locations;

    return headerLayer;

}

@end

We will use that later. Now lets add some properties to the ViewController.h for the rfduino, text field and UILabel for the device name that we will display.

#import <UIKit/UIKit.h>
#import "RFduino.h"
#import "RFduinoDelegate.h"

@interface ViewController : UIViewController<RFduinoDelegate>

@property(nonatomic, strong) RFduino *rfduino;
@property (nonatomic,strong) IBOutlet UITextField *textField;
@property (nonatomic, strong)  UILabel *deviceName;

@end

Lets do something with these properties. Open the ViewController.m file and start to copy the below code into the file. This isn’t all of the file btw so don’t try to run it just yet!

#import "ViewController.h"
#import "BackgroundGradient.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize deviceName, rfduino, textField = _textField;

- (void)viewDidLoad
{
	//hides the navigation bar
    [super viewDidLoad];
	[self.navigationController setNavigationBarHidden:YES];

	//set background colour gradient
	CAGradientLayer *bgLayer = [BackgroundGradient blueGradient];
	bgLayer.frame = self.view.bounds;
	[self.view.layer insertSublayer:bgLayer atIndex:0];

	//Device Name
	NSString *deviceText = [[NSString alloc] initWithFormat:@"%@", rfduino.name];
	deviceName.text = deviceText;
}

Hopefully this all makes sense. We are just synthesising the properties we created earlier, hiding the navigation bar and setting up both the background colour gradient and the device name label. If you don’t want a gradient background just miss out the middle three lines.

Lets connect some of this up. Open the main storyboard and connect the default label to the outlet for deviceName (ctrl+click and drag from the yellow box onto the blank label, select deviceName under outlets). Then do the same for the textField, linking it to the textField.

While the textField is highlighted also change some of the parameters in the inspector to these.
Screen Shot 2014-09-01 at 21.45.30

 

Now open the assistant editor in the top right of Xcode so both the main storyboard and ViewController.m are open. Ctrl drag from the Clear All button to an empty space in ViewController.m. Label the newly created IBOutlet clearAll and add the following code.

- (IBAction)clearAll:(id)sender {
	//Clears all data from string on the arduino and text field
	[_textField resignFirstResponder];
	NSString *identifier = @"0";
	NSData *data = [identifier dataUsingEncoding:NSASCIIStringEncoding];
	[rfduino send:data];
	_textField.text = nil;
}

Do the same for disconnect using the below code.

- (IBAction)disconnectDevice:(id)sender {
	[_textField resignFirstResponder];
	[rfduino disconnect];
}

Finally, we need to control the textField. The easiest way to do this is to set the textField’s delegate as the ViewController. With the storyboard open in the standard editor view click on the textField so it is highlighted.Open the connection inspector and drag the plus symbol next to the outlet delegate to the ViewController underneath where it says ViewController Scene.

I thought the best way to trigger the method to send that typed data would be to use the send key on the keyboard. To do this implement the code below. Hopefully the comments will explain what is going on. I’m not saying any of this is best practice by the way but it has worked for me. Please feel free to improve it and comment back to me!

//sends data when "send" is pressed on keyboard
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
	_textField = textField;
	//max data is 12 chars
	//1 is taken up for identifier

	//remove keyboard
	[_textField resignFirstResponder];

	//work out the amount of packets that need to transmitted
	//int a = (dividend + (divisor - 1)) / divisor;
	NSInteger packets = (((_textField.text.length)+ (11-1))/11);

	//Splits the text string into 11-character substrings then sends them with associated packet number
	for (int i = 0; i<(packets) ; i++){
		if ((11*(1+i)) < _textField.text.length){
			NSInteger packetIdentifier = 2;
			if (i == 0) packetIdentifier = 1; //first packet to be sent needs identifier 1
			NSString *subStr = [_textField.text substringWithRange:NSMakeRange((0+(11*i)), 11)];
			NSString *identifier = [NSString stringWithFormat:@"%ld", (long)packetIdentifier];
			NSString *sendPartial = [identifier stringByAppendingString:subStr];
			NSData *data = [sendPartial dataUsingEncoding:NSASCIIStringEncoding];
			[rfduino send:data];
		}else{
			NSInteger packetIdentifier = 2;
			if (i == 0) packetIdentifier = 1;  //first packet to be sent needs identifier 1
			NSString *subStr = [_textField.text substringWithRange:NSMakeRange((0+(11*i)), (_textField.text.length-(0+(11*i))))]; //corrects the packet length incase the string is not 11 characters long
			NSString *identifier = [NSString stringWithFormat:@"%ld", (long)packetIdentifier];
			NSString *sendPartial = [identifier stringByAppendingString:subStr];
			NSData *data = [sendPartial dataUsingEncoding:NSASCIIStringEncoding];
			[rfduino send:data];
		}
	}
	return YES;
}

Unless I have forgotten something this will now work. Run the app with the RFduino on and send strings of length >12 to your heart’s content. It should look like this when complete.

IMG_2167

IMG_2168

 

You may find it annoying if you want to dismiss the keyboard without sending a message. The best way I found to do this was to make a transparent, unlabelled button that is the size of the screen. Position it behind all other buttons then implement the following IBAction when it is pressed.

- (IBAction)removeKeyboard:(id)sender {
	//if user presses anywhere but the keyboard it will disappear
	[_textField resignFirstResponder];
}

All should now work perfectly. I decided to make the text of my buttons and labels white to make it look a bit nicer.

All of the code is on Github https://github.com/wingoodharry/RFDuinoLCD

Hopefully that was useful. This is my first attempt at iOS so please let me know if I am incorrect in any way and I will try to adapt and learn!

 

 

Using Jsoup with Android — August 11, 2014

Using Jsoup with Android

As promised, we will now look at using Jsoup with Android. This is pretty simple and very similar to the previous java example where we parsed the title from Wikipedia’s page. By keeping it bare bones and simple you should see how this works and be able to add more to it gradually.

Start by making a new Android project with a blank activity and blank layout. Add the Jsoup .jar into the libs directory of your project and add to the build path.

Get the quickest/easy thing out the way by putting the following in your manifest.xml file beneath the uses SDK section. We are going to be using the device’s Internet connection so you need a permission to do so.

  <uses-permission android:name="android.permission.INTERNET"/>

Copy the code below for your layout file. It is just a button and a textView with IDs so we can access them from the main activity.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.jsouptest.MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:text="Button" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="42dp"
        android:text="TextView" />

</RelativeLayout>

Now change your Main Activity to look like the below. I have commented in the code to try and explain what is going on.

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import android.support.v7.app.ActionBarActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

	String url = "http://www.wikipedia.org";
	Document doc = null;
	TextView textView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView1);
        Button button = (Button) findViewById(R.id.button1);

        button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				textView.setText("WORKING"); //just to show button has been pressed
				new DataGrabber().execute(); //execute the asynctask below
			}
		});

    }
    //New class for the Asynctask, where the data will be fetched in the background
    private class DataGrabber extends AsyncTask<Void, Void, Void>{

		@Override
		protected Void doInBackground(Void... params) {
			// NO CHANGES TO UI TO BE DONE HERE
			try {
				doc = Jsoup.connect(url).get();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			//This is where we update the UI with the acquired data
			if (doc != null){
				textView.setText(doc.title().toString());
			}else{
				textView.setText("FAILURE");
			}
		}
    }
}

I suppose the main thing that is out of the ordinary here is having a new class (DataGrabber) that extends AsyncTask. The reason is that if you want to get data from a server or the internet like we are you cannot do it from the main UI thread. This is so that if it takes some time it won’t make the UI unresponsive. It is quite simple though, as you see I have just used the method doInBackground to get the URL and then used onPostExecute to modify my UI with the result (you can’t modify the UI from a background task!). More info on all that here if you are interested.

Run the app on a device with Internet access and if all has worked well you should see something like this:

Screenshot_2014-08-10-21-54-48

Now experiment by trying to get other information out of other websites, like the last post. If you want to see this in action I have used it in an app of mine. Its pretty simple but does what it needs to.

Hopefully that was helpful. Let me know if anything needs greater detail.

 

Attempting to use JSOUP — August 10, 2014

Attempting to use JSOUP

Recently a friend asked me if it was possible to extract data from a website and display it on an Android device, rather than having a dedicated app pulling data from a server. I did a bit of research and found that with the help of Jsoup it may not be that hard at all.

Jsoup is a Java library that can manipulate HTML data from a source, be it a file website or string etc. This allows us to scrape and parse websites for the data that we wish to collect quite easily and succinctly. As it is a Java library it can also be used on Android with no hassle. The best way to start with Jsoup is to just use it in a simple Java program that will print the results to the console.

First download the Jsoup .jar from here. There are lots of good explanations and resources on the website so have a look around.

Make a new java project, add a ‘lib’ folder to your project directory and copy the .jar file inside it. Hit refresh (F5) and then right click on the .jar file in the lib folder. Select ‘add to build path’. You will then see the .jar file will move from lib to the referenced libraries location in your project. If you need any further assistance with that look here.

Just for an easy example and to see how it works I am just going to take the title off of http://www.wikipedia.org using Jsoup. Create a new class and use the following code.

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

public class Main {

	public static void main(String[] args){

		String url = "http://www.wikipedia.org";

		Document doc = null;
		try {
			doc = Jsoup.connect(url).get();
		} catch (IOException e) {
			// TODO Auto-generated catch bloc
			e.printStackTrace();
		}
		String title = doc.title();
		System.out.println(&quot;Title = &quot;+ title);
	}
}

If you run that code it should print “Title = Wikipedia”. Not much is really going on here. We are just passing the url string to the Jsoup connect interface, where get() is then called which will return a parsed Document for us to work with from the original url.

All we do then is use .title() on doc, which returns a string of the document’s title. If you look at the below snippet of html from Wikipedia.org you will see why this works.

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;mul&quot; dir=&quot;ltr&quot;&gt;
&lt;head&gt;
&lt;!-- Sysops: Please do not edit the main template directly; update /temp and synchronise. --&gt;
&lt;meta charset=&quot;utf-8&quot;&gt;
&lt;title&gt;Wikipedia&lt;/title&gt;

What if we wanted the Wikipedia logo image though instead? Easy enough, all we have to do is change the last two lines of code to the below.

Element img = doc.getElementsByTag(&quot;img&quot;).first();
System.out.println(img.toString());

Run that and you should get the url source for the Wiki image display in your console.

Jsoup is searching the HTML document doc for elements with the tag “img” and then printing that Element to the console using .toString(). Also notice I used .first() because I only wanted the first image. Take it out and se how many you get now!

Again this makes more sense if you look at the HTML for the wiki page.

&lt;h1 class=&quot;central-textlogo&quot; style=&quot;font-variant: small-caps;&quot;&gt;
&lt;img src=&quot;//upload.wikimedia.org/wikipedia/meta/6/6d/Wikipedia_wordmark_1x.png&quot; srcset=&quot;//upload.wikimedia.org/wikipedia/meta/a/a9/Wikipedia_wordmark_1.5x.png 1.5x, //upload.wikimedia.org/wikipedia/meta/8/8a/Wikipedia_wordmark_2x.png 2x&quot; width=&quot;174&quot; height=&quot;30&quot; alt=&quot;WikipediA&quot; title=&quot;Wikipedia&quot;&gt;
&lt;/h1&gt;

You might be questioning what is the use of this but let me assure you it can be useful. The code below gets all the fixtures for a month from this website and formats them into easy readable data on the console. Give it a go. I’ve tried to explain how it works using comments in the code.

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Main {

	public static void main(String[] args){
		String url = "http://www.national-autograss.co.uk/march.htm";
		Document doc = null;
		Element table = null;
		Elements rows = null;
		Element date = null;
		Elements tables = null;
		try {
			doc = Jsoup.connect(url).get();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		tables = doc.select("table"); //gets all the table elements from doc 

		//how many table elements were parsed
		for (int t = 0; t < (tables.size() - 1); t++){
			table = tables.get(t);      	//get singular table element
			rows = table.select("tr");  	//get the rows from the table element
			date = doc.select("h2").get(t);	//get date from h2 field.

			/*there is a date for each table on this website so I use the
			 * t from table size to get the appropriate one
			 */
			System.out.println("********" + date.text() + "********");

			Elements data = null;
			//cycle through the rows getting the data from each cell of data td.
			//I started at one because I dodn't want the titles
			for (int i = 1; i < rows.size(); i++){
				data = rows.get(i).select("td");

				for (int k = 0; k < data.size(); k++){
					//go through td data of row and print out
					System.out.println(data.get(k).text());
				}
			}
		}
	}

You will get the following in your console if it has worked correctly:

********Sunday 09 March********
Nottingham
Oxton
10:30am
RO
Single Days Racing

********Sunday 16 March********
Carlow
knocknatubbrid
12:00noon
RO/Q
Single Days Racing

Pennine
Darleymoor
11:00am
RO
Single Days Racing

And so on…

The key to understanding how this all works is really knowing how HTML tables work. I found this website quite handy but this is all you really need to know for this from W3 schools):

HTML Tables
Tables are defined with the table tag.

A table is divided into rows with the tr tag. (tr stands for table row)

A row is divided into data cells with the td tag. (td stands for table data)

The td elements are the data containers in the table.

The td elements can contain all sorts of HTML elements like text, images, lists, other tables, etc.

In the next post I will show you how to use this in an Android app.

Cheers

RFDuino Beginnings — June 11, 2014

RFDuino Beginnings

I have been flirting with BLE for a while now, using different modules such as the RedBear Labs Arduino shield and the Dorji UART module. There is nothing wrong with either product both are great at what they do, however one is limited to UART and the other is rather large. Both require an external micro controller to do anything cool with.

Anyway, I found the RFduino and ordered one. I managed to get it all working within 20 minutes so here are my initial thoughts and findings. You will need an iOS device (4S onwards have BLE)  to get what I have in this blog working. I will cover how to get a custom iOS and Android app working  with this shortly.

First thing to note is the size of it. It is very small considering that you have both the micro controller and BLE circuitry all in one tiny package. The picture below shows the USB programmer and the RFduino on a dev board. If you were to drop the RFduino directly onto your own PCB it would only take up less than 20x20mm! Considering you are also getting an ARM Cortex M0 that can be programmed like an Arduino it really does become quite useful.

IMG_1814

The above only costs £30 from RS, the RFduino PCB singular is £10 which does make this quite a cheap package if you are wanting to start experimenting with BLE.

Setting up the RFduino is mostly a simple task if you have used any similar hardware etc but there is also plenty of information at RFduino.com for any in depth help. I will just glide over it to give a brief synopsis of what is needed. Feel free to message me with any questions if you like!

1. Get the latest Arduino IDE from here and install on your PC/Mac. You will need the 1.5.6 R2 build, as there is support for ARM architectures etc

2. Download the RFduino zip package from here. Unzip and place in the following directory: programFiles/Arduino/Hardware/arduino (there should be two folders in the directory already called ‘sam’ and ‘avr’ to make sure you are in the right place). On a mac go to applications and right click the Arduino application, select show ‘show package contents’. Then drop the file in: contents/resources/java/hardware/arduino. This gives the Arduino IDE the information to program the RFduino.

3. Open the RFduino folder and then the libraries folder inside it. Copy the RFduinoBLE folder and place it in the Arduino libraries folder (this will be found at the same level as the hardware folder). This will give us all of the RFduino example code.

4. Now all that is needed is to set up your PC/Mac to connect to the USB programmer. The programmer uses an FTDI chip so download the correct VCP FTDI driver for your system from here and install. There is quite a handy FAQ section on their website if you face difficulties – I did.

Now plug in your RFduino. Open the Arduino IDE and load the temperature sketch from the RFduino section of the examples section. I like chose this one because it involves no other hardware. Select ‘RFduino’ as your board and finally set your COM port correctly, usually this is automatic on Windows (normally tty.usbserial on a mac). Both parts are pictured below.

30

10

 

 

 

 

 

Now upload the sketch to the RFduino. ‘Success’ should be displayed in orange in the console at the bottom of the IDE if all has gone well. If you get an error, check that your files are in the right place in the hardware and libraries directories. You may have noticed nothing seems to be acting any different.

Get your iOS device out and download the RFduino temperature sample app from the App Store. https://itunes.apple.com/us/app/rfduino-temperature/id668832196?mt=8

Turn Bluetooth on in settings on your iOS device and load the app. You should now see a list view with one entry showing your RFduino. Press the RFduino entry in the list and it will change view to show you the current temperature from the RFduino board on your iPhone screen. Easy as that.

IMG_1870

IMG_1871

 

 

 

 

 

 

I would now look at the rest of the examples and see what you can make. RFduino have been generous enough to supply the source Xcode projects for the iPhone apps too in the RFduino folder. There are also more finished sample apps on the App Store if you search for RFduino.

So far I have managed to get some very interesting projects going by reworking the example sketches and iOS source code. I really like how this allows me to concentrate on the app development side (which is what I am predominantly interested in) without having to spend a lot of time producing hardware. There are some limitations; at this point I don’t believe there is an easy way to have a secure pairing between devices but I am hopeful to get a work around.

Below is a screenshot of the current example sketches from RFduino. As you can see there is a wide selection, from servo control, proximity, to iBeacons.

20

Sorry that this doesn’t go into much depth today but I thought it best to get the foundations down first. Very soon I will go through how to modify both the sketch and the iOS sample app so that we can get a bit more functionality.

I hope that was useful in some way. Comment if I missed something etc.

 

UART with Bluetooth Low Energy (BLE) using Dorji DBM01 — April 24, 2014

UART with Bluetooth Low Energy (BLE) using Dorji DBM01

I found these modules while I was browsing for some development products on ebay. They promised to make it very simple to communicate between a BLE device (Android/iOS etc) and any device that can communicate via serial UART.

Of course I had to give them a go, especially for the price. Because all of the BLE profiles have already been taken care of, this is a useful product if you wish to develop an application sending simple data to and from BLE devices.

To get started with this BLE module you will need a few things: BLE compatible iOS device (Android will work too but I am using iOS), PC with a terminal application installed, 3.3V supply and RS232 level converter. The pin out for the module is below, we only need 4 pins though. Ground, Vcc, Tx, Rx.Screen Shot 2014-04-24 at 20.47.48

**An interesting thing before we go any further**

The module I am using is pre December 2013 so does not utilise the P0.6/CTRL pin. If you are lucky and are using a more modern module you can set whether your device works in transparent mode (pin HIGH) or via AT commands (pin LOW). For this example you would use transparent. AT commands are very useful, especially to set the device up to your owns specifications (change role from peripheral to central for example!) More information can be found here.

**

Back to the fun stuff. Solder some thin cable to the correct pins or make a PCB if you have equipment. I was impatient so I soldered directly to the module. If you solder direct I would recommend anchoring the board in place with something as it is extremely light.

IMG_1594

 

Buzz out the pins to make sure you have no shorts with a multimeter and connect the module up to a power supply. I used the 3.3V off of my Arduino. Now download LightBlue from iTunes to test whether it works! Open the app and you should see your BLE peripheral on the screen.

 

IMG_1596

 

Now the easy bit. Connect the Tx and Rx from the BLE module to your RS232 level converter’s associated ports. I used a USB to TTL converter, which makes this process a lot quicker than a MAX chip on a breadboard. I recommend them highly. My finished, albeit messy circuit is below.

 

IMG_1595

 

Once connected you need to set up Realterm or Hyperterminal (or any other terminal app) so that the connection setup reads 38400 baud, 8 data bits, Parity None, 1 stop bit, no flow control. With your PC terminal connected, open the LightBlue app again and tap on your BLE device. The screen below should appear.


IMG_1597

 

The BLE service we want to use is 0xFFF0 so press that and the screen will change to a menu of different characteristics. BLE services and characteristics are quite large subjects and I’m not that bright so I won’t go into them here but there is a plethora of information available from a quick google search.

 

IMG_1598

 

From the Dorji data sheet we know that characteristic 0xFFF1 is the write data property so press that to bring up the write screen.
IMG_1599

 

 

Now type in a string of characters in the ASCII box and hit send. Hopefully you will see that the message has been received on your PC’s terminal window.

 

IMG_1600

Now you have no excuse to make the next big thing, from wearables to swanky remotes. It is all possible!!

If for some reason your attempt has not worked I would check firstly your electrical connections for open circuits and shorts. Then check your PC terminal with a known working device or simply plug tx into rx and make sure what you type in the terminal is echoed back on the same screen.

I hope this has been some sort of help or interest. If you have any questions feel free to message me.