Past posts have built an atMega328p nano board with bluetooth BLE and a DHT22 sensor, and also a quick peek at Python on a Raspberry Pi 0w. Now it’s time to combine them.
Make sure your Pi is up to date if you haven’t already:
sudo apt-get upgrade
sudo apt-get dist-upgrade
And make sure that you have the bluez libraries and the python :
sudo apt-get instal blues pi-bluetooth
It appears that as of this writing (the end of 2018), all of the services needed for BLE are now included by default, and that it is not necessary to manually add support for experimental portions
Use ssh to connect to your py, and make sure bluetooth is up:
pi@sprinklers:~ $ systemctl status bluetooth
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset
Active: active (running) since Fri 2018-12-28 22:39:21 UTC; 39s ago
Docs: man:bluetoothd(8)
Main PID: 352 (bluetoothd)
Status: "Running"
CGroup: /system.slice/bluetooth.service
└─352 /usr/lib/bluetooth/bluetoothd
Dec 28 22:39:20 sprinklers systemd[1]: Starting Bluetooth service...
Dec 28 22:39:21 sprinklers bluetoothd[352]: Bluetooth daemon 5.43
Dec 28 22:39:21 sprinklers systemd[1]: Started Bluetooth service.
Dec 28 22:39:21 sprinklers bluetoothd[352]: Starting SDP server
Dec 28 22:39:21 sprinklers bluetoothd[352]: Bluetooth management interface 1.14
Dec 28 22:39:21 sprinklers bluetoothd[352]: Failed to obtain handles for "Servic
Dec 28 22:39:21 sprinklers bluetoothd[352]: Sap driver initialization failed.
Dec 28 22:39:21 sprinklers bluetoothd[352]: sap-server: Operation not permitted
Dec 28 22:39:21 sprinklers bluetoothd[352]: Failed to set privacy: Rejected (0x0
It is the second and third line that interest us: the daemon is running and active.
Now look for your device from the command line with blescan:
pi@sprinklers:~ $ sudo blescan
Scanning for devices...
Device (new): 7c:01:0a:7c:d1:9e (public), -67 dBm
Flags: <06>
Incomplete 16b Services: <0000ab12-0000-1000-8000-00805f9b34fb,0000fee0-0000-1000-8000-00805f9b34fb>
Complete Local Name: '=BT_lawn_1'
Manufacturer: <8ef088a07c010a7cd19e>
Device (new): 44:f7:fe:c4:3b:ea (random), -57 dBm
Flags: <1a>
Manufacturer: <4c001005031cc20019>
Device (new): 46:ad:82:a9:2c:c6 (random), -82 dBm
Flags: <1a>
Manufacturer: <4c001005031caf2bee>
Lines starting with “Device” indicate a new device. So a few lines down, we see my BT_lawn_1 device, and its ID “7c:01:0a:7c:d1:9e”.
Now paste this program into blemcp.0001.py:
#blemcp.py
#monitor and control the garden ble devices
# needed services
#we need the btle package from bluesy
from bluepy import btle
#eventually we'll loop forever and doze between
while True :
#connect to this device as "lawn"
#you need to use your own ID here, as shown in the aritcle
lawn=btle.Peripheral("7c:01:0a:7c:d1:9e")
# at this point, the led on the AT-09 should change from blinking to
# on, as you are connected.
#now, list the services we have.
for service in lawn.services:
print str(service)
# we really don't want to loop forever. yet, so break out of this and exit
# (note that your led will return to blinking.
break
print "***splat***"
Now run it:
pi@sprinklers:~ $ ./blemcp.0001.py
Service <uuid=Generic Attribute handleStart=12 handleEnd=15>
Service <uuid=Generic Access handleStart=1 handleEnd=11>
Service <uuid=ab12 handleStart=35 handleEnd=65535>
Service <uuid=Device Information handleStart=16 handleEnd=34>
***splat***
The LED should have changed briefly to solidly on (as would the status LED if you have it attached), and then returned to blinking (and the status LED to off).
Congratulations. This establishes proof of life; your Pi and atMega are talking! Now let’s make it do something.
This script, blemcp.0002.py, will actually send the “y” command to turn on the LED. How, you may wonder, did I come up with the values, particularly “37”, in this script? If I were to reply with “black magic”, my priest would probably be disturbed, so I won’t.
Rather, A lot of web searching, reading broken examples in questions, trial, error, and headbanging on the wall. From lightblue, I determined that AB12 was the service address for talking to the AT-09. This didn’t really get me anywhere, other than determine that there is such a service on my chip when I assign a value to s.
So why not just RTFM? [this article interrupted while we wait for the author to cease rolling on the floor in hysterics and climb back into his chair, which the cat will no doubt have claimed by then.]
OK, where were we? Oh, documentation. Yeah. Good luck. It seems to be a wonderful library, and you can find the lists of functions for classes, but what they actually mean and the format of the returned lists is, well, . . . so I resorted to trial and error.
Then from the available commands from AT+HELP, I also found this UUID with “AT+UUID”, while “AT_CHAR” revealed “0101”. This I used to search through the characteristics from lawn.getDescriptors(), and looked for 0101 in the loop. With this, I knew to use 37 as the characteristic to write.
Putting these together, we get the single program that puts all of these together:
#!/usr/bin/python
#blemcp.0002.py
#monitor and control the garden ble devices
# needed services
#we need the btle package from bluesy
from bluepy import btle
#connect to this device as "lawn"
#you need to use your own MAC address here, as shown in the aritcle
lawn=btle.Peripheral("7c:01:0a:7c:d1:9e")
# at this point, the led on the AT-09 should change from blinking to
# on, as you are connected.
s = lawn.getServiceByUUID(0xAB12)
print "s: ",str(s)
characteristics= lawn.getDescriptors()
for k in characteristics:
print k, k.uuid, k.handle
#eventually we'll loop forever and doze between
while True :
#now, tell it to tun on its LED
lawn.writeCharacteristic(37, 'y')
# we really don't want to loop forever. yet, so break out of this and exit
# (note that your led will return to blinking.
break
#manualy disconnect, just for good mesure
# we could use lawn.disconnect(), but we have a routine to do so
# on our atMega
lawn.writeCharacteristic(37, 'k')
print "***splat***"