I created Blue Dot after being asked many times at Picademy “how can I get rid of all these wires?”.
Blue dot is an android app (client) and really easy to use Python library which allows you to wirelessly control your Python projects, whether that is a light switch, remote camera, robot or anything else you can think of!
See the getting started guide for more info on 'getting started', or follow the tutorial below.
Installation & Use
These instructions assume your Raspberry Pi is running the latest version of Raspbian with Pixel.
You will need a Raspberry Pi with built-in Bluetooth (such as the Pi 3 or Pi Zero W) or a Raspberry Pi and a USB Bluetooth dongle.
Get the app
Download and install the Blue Dot app from the google play store.
If you are wondering why there is no iOS app? Its because iOS doesn't support Bluetooth serial comms; you can only really talk to 'standard devices' (cars, speakers, fitness trackers, etc).
Python library
Open a terminal (Menu > Accessories > Terminal) and type:
sudo apt-get install python3-dbus sudo pip3 install bluedotOr if you need to use Python 2 (please dont tho!):
sudo apt-get install python-dbus sudo pip install bluedot
Pairing
In order to communicate over Bluetooth securely you need to pair your phone to your Raspberry Pi.
On your Android phone:
- Open Settings
- Select Bluetooth
- This will make your phone Discoverable
- Click the bluetooth icon on the taskbar
- Turn on Bluetooth (if its off)
- Click Make Discoverable
- Click Add Device
- Your phone will appear in the list, select it and click Pair
- Enter a PIN code
- Enter the same PIN code when prompted
- Click Ok
The simplest way to use the Blue Dot is as a button:
- Open Python 3 (Menu > Programming > Python 3)
- Create a new file (File > New File)
- The following code, will start up the Blue Dot, and wait for it to be pressed:
- Save your program (File > Save) as mydot.py
- Run your program (Run > Run Module)
- Open the Blue Dot app
- Connect to your Raspberry Pi
- Press the Blue Dot
from bluedot import BlueDot bd = BlueDot() bd.wait_for_press() print("You pressed the blue dot!")
from bluedot import BlueDot from signal import pause def say_hello(): print("Hello World") def say_goodbye(): print("goodbye") bd = BlueDot() bd.when_pressed = say_hello bd.when_released = say_goodbye pause()By using the position of where the button is pressed you can use the Blue Dot like a joystick:
from bluedot import BlueDot from signal import pause def dpad(pos): if pos.top: print("up") elif pos.bottom: print("down") elif pos.left: print("left") elif pos.right: print("right") elif pos.middle: print("fire") bd = BlueDot() bd.when_pressed = dpad pause()Add to this gpiozero's Robot functions, you can create a Bluetooth controlled robot with very little code.
from bluedot import BlueDot from gpiozero import Robot from signal import pause bd = BlueDot() robot = Robot(left=(lfpin, lbpin), right=(rfpin, rbpin)) def move(pos): if pos.top: robot.forward() elif pos.bottom: robot.backward() elif pos.left: robot.left() elif pos.right: robot.right() def stop(): robot.stop() bd.when_pressed = move bd.when_moved = move bd.when_released = stop pause()Check out the Blue Dot documentation for more information and ideas - you really can do a lot with a simple circle :)
brilliant! Will play with this soon
ReplyDeleteWe've been getting stuck into using Blue Dot since seeing you demo it at the Manchester Raspberry Pi Jamboree in May. We're using David Glaude's stuff to control our Unicorn Hat/ Ikea lamp at https://github.com/dglaude/Blue-Dot-Colour-Picker . Many thanks.
ReplyDeleteExcellent, I saw David's work and instantly thought of you but I didnt have any contact details for you (and couldn't find you on twitter), so Im glad you found it.
DeleteI'm afraid social media has passed me by but obviously some sort of telekinesis got me to enter the right things in Google. Perhaps it just shows how Google tends to constrain discovery ?
ReplyDeleteMartin, thank you very much for this incredibly brilliant blue dot! Fine documentation, good API, ... very-very well done! Is the Android app source code also available?
ReplyDeleteOh, never mind, missed https://github.com/martinohanlon/BlueDot/tree/master/clients/android
ReplyDeleteHi Martin,
ReplyDeleteExactly what I was looking for.
Just installed and used your project with my robot. Worked like a dream. Well done, keep up the good work.
Very pleased to here it.
DeleteThis comment has been removed by the author.
ReplyDeleteMartin,
ReplyDeleteI was wondering if it would be a good idea to add couple of circles to the BlueDot to create zones. Only visual. The code to determine which zone is being used/pressed/released can be done using simple distance/angle conditions like so:
def move(pos):
....# outer circle:
....if pos.distance > .85:
........if -45 < pos.angle <= 45:
............robot.forward()
........elif pos.angle > 135 or pos.angle <= -135:
............robot.backward()
........elif 45 < pos.angle <= 135:
............robot.right()
........elif -135 < pos.angle <= -45:
............robot.left()
....# middle circle:
....elif .45 < pos.distance <= .85:
........if -45 < pos.angle <= 45:
............robot.spine_up()
........elif pos.angle > 135 or pos.angle <= -135:
............robot.spine_down()
........elif 45 < pos.angle <= 135:
............robot.base_clockwise()
........elif -135 < pos.angle <= -45:
............robot.base_counterclockwise()
....# inner circle:
....elif pos.distance <= .45:
........if -45 < pos.angle <= 45:
............robot.arm_up()
........elif pos.angle > 135 or pos.angle <= -135:
............robot.arm_down()
........elif 45 < pos.angle <= 135:
............robot.neck_up()
........elif -135 < pos.angle <= -45:
............robot.neck_down()
Hi Martin.
ReplyDeletewhy will my pi and phone pair up but they wont connect! the pi says no usable services. have tried brand new install plus update etc and followed instructions.
Do you get the message "no usable services" when you do the pairing? If so, you can ignore it, you phone and Pi are still paired, it basically telling you that there are no registered services running on the Pi (yet).
DeleteRun Blue Dot and it should connect.
I have put a small note on the getting started guide. I had already put it on the pairing Pi to Pi instructions, but not the Pi to Android instructions!
DeleteHi Martin!
ReplyDeleteThis is really good stuff. Thanks a lot. I have a quick question. In the BT Comm code sample you provide, is there a way to terminate the server side at some point? I've tried "s.stop()", but that did not work.
Thanks in advance.
There is a s.stop() method. http://bluedot.readthedocs.io/en/latest/btcommapi.html#bluedot.btcomm.BluetoothServer.stop
DeleteWhen you tried it, what happened, did you receive an error?
This is the return:
DeleteException in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
self.run()
File "/usr/lib/python3.4/threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.4/dist-packages/bluedot/btcomm.py", line 397, in _wait_for_connection
self._read()
File "/usr/local/lib/python3.4/dist-packages/bluedot/btcomm.py", line 418, in _read
self.data_received_callback(data)
File "/home/pi/Scripts/startup_bluetooth.py", line 39, in data_received
s.stop()
File "/usr/local/lib/python3.4/dist-packages/bluedot/btcomm.py", line 360, in stop
self._conn_thread.stop()
File "/usr/local/lib/python3.4/dist-packages/bluedot/threads.py", line 26, in stop
self.join()
File "/usr/local/lib/python3.4/dist-packages/bluedot/threads.py", line 29, in join
super(WrapThread, self).join()
File "/usr/lib/python3.4/threading.py", line 1057, in join
raise RuntimeError("cannot join current thread")
RuntimeError: cannot join current thread
Thanks. Could you raise an issue on github.com/martinohanlon/BlueDot please. Could you also include your code and I will take a look at it for you.
DeleteJust had a quick look at your stack trace. Are you by any chance trying to stop the server within your data_received function? i.e. you code looks a bit like this:
Delete|def data_received(data):
| # do stuff
| s.stop()
|
|s = BluetoothServer(data_received)
if so I can understand why you are getting an error. In summary, you cant stop the server because the thread you are trying to stop is the one running the data_received function i.e. you cant stop yourself!
If you could raise an issue I'll have a think about how that might be resolved, but in the mean time, call stop outside the data_received function, something like this:
|run_server = False
|def data_received(data):
| # do stuff
| stop_server = True
|
|s = BluetoothServer(data_received)
|while stop_server == False:
| time.sleep(0.1)
|s.stop()
Excellent work Martin, I really like the dot!!!
ReplyDeleteIn the "Variable Speed Robot"-example, only 4 pins are used to control 2 motors? However, a h-bridge like L298n requires 6 pins, where 2 are for PWM. Can you please explain how it works with only 2 pins per motor and how to wire to a L298n board. Ref pic here: https://tronixlabs.com.au/news/tutorial-l298n-dual-motor-controller-module-2a-and-arduino
Many thanks!
Martin