$ lpstat -v device for Epson_Stylus_Photo_R2000: lpd://192.168.1.214:515/PASSTHRU $ escputil -P Epson_Stylus_Photo_R2000 -n Escputil version 5.3.3, Copyright (C) 2000-2006 Robert Krawitz Escputil comes with ABSOLUTELY NO WARRANTY; for details type 'escputil -l' This is free software, and you are welcome to redistribute it under certain conditions; type 'escputil -l' for details. Running nozzle check, please ensure paper is in the printer.
Migration to wordpress finished
Not everything is ready, there are some broken links etc, but the main part of the blog has been moved.
OpenCyclingComputer is finally reaching the “road ready” stage:
- BLE connection with heart rate sensor. Also automatic re-connection and graceful quiet handling of all errors from bluez stack.
- BLE connection with speed and cadence sensor. It’s really wheel revolution and cadence sensor, but given wheel size it works as speed sensor.
- Pressure sensor. Iit will be used as an altimeter in the near future. Coded with Kalman filter
- Temperature sensor
- GPS module – I still need to do some debugging here, but the drivers were tested on raspberry A+ and worked great.
- YAML layouts. It’s very easy to change the default layout – it’s simply a text file + some background images.
- Saving / reading config file. Also YAML, so it’s a human editable.
- “Animated” heart rate and cadence icons showing that the related sensors are “alive” and keep sending notifications.
- All settings can be edited from the OCC screen
Things that need polishing:
- Calculating averages (speed, heart rate, etc)
- Implementing Kalman filters where suitable
- BLE scanning and selecting devices from the OCC screen
- Calculating altitude and all related parameters like slope, pressure at sea level and others
- BLE status icon works, but it doesn’t show exactly what’s happening with the connection
- Implementing Low Battery warning/shut down (hardware is ready)
- Improving ride log. Currently the format of the log is hard coded
- defining sensor API for future extensions
- plugging accelerometer into the current system
- implementing inertion+gps navigation with multi input Kalman filter
- code cleaning and refactoring
I used to use pygame, but outdated SDL problems resulting in malfunctioning touchscreen forced me to use a different solution. Touchscreen works with python-evdev and I needed graphics. Cairo is the obvious choice for 2D and after a few days of playing with different solutions I came up with this:
#Very simple way of accessing PiTFT 240x320 display from python with cairo import mmap import cairo # 320 * 240 * 2 bytes per pixel = 153600 PiTFT_mem_size = 153600 # Framebuffer file, might be /dev/fb0 fb_fd = open("/dev/fb1", "r+") #Map the framebuffer to memory fb_map = mmap.mmap(fb_fd.fileno(), PiTFT_mem_size) #Create cairo surface. If you get "Function not implemented" error, you need a newer cairo surface = cairo.ImageSurface.create_for_data(fb_map, cairo.FORMAT_RGB16_565, 240, 320) #Create cairo context cr = cairo.Context(surface) # Paint the surface black cr.set_source_rgba (0.0, 0.0, 0.0, 1.); cr.paint_with_alpha (1.0); for i in range(0, 10): c = i / 10.0 cr.set_source_rgb (1.0 - c, 1.0 - c, 1.0) cr.rectangle(15 * i + 10, 15 * i + 20, 100, 100) cr.fill () #Close the mapped framebuffer fb_map.close()
That’s how it looks on the piTFT:
Pi Zero W is the new brain of the Open Cycling Computer. PiTFT 2.8″ capacitive dosn’t work out-of-the-box, but required modification are very simple.
Modifications required in /boot/config.txt
1. Uncomment dtparam=spi=on
2. Add dtoverlay=pitft28-capacitive,rotate=90,speed=32000000,fps=20
Modifications required in /boot/cmdline.txt
1. Add after rootwait (the end of line) fbcon=map:10 fbcon=font:VGA8x8 logo.nologo
That’s it! No other modifications are required.
P.S. 31-Mar-2017: Do not install adafruit kernel as it doesn’t support bluetooth/wifi on Pi Zero W yet.
$ ./btle.py fd:df:0e:4e:76:cf random Connecting to: fd:df:0e:4e:76:cf, address type: random Service <uuid=Generic Access handleStart=1 handleEnd=7> : Characteristic <Device Name>, hnd=0x2, supports READ WRITE -> 'Lezyne S&C 249' Characteristic <Appearance>, hnd=0x4, supports READ -> '\x85\x04' Characteristic <Peripheral Preferred Connection Parameters>, hnd=0x6, supports READ -> '\x80\x02H\x03\x00\x00\x90\x01' Service <uuid=Cycling Speed and Cadence handleStart=12 handleEnd=22> : Characteristic <CSC Measurement>, hnd=0xd, supports NOTIFY Characteristic <CSC Feature>, hnd=0x10, supports READ -> '\x07\x00' Characteristic <Sensor Location>, hnd=0x12, supports READ -> '\x04' Characteristic <SC Control Point>, hnd=0x14, supports INDICATE WRITE Service <uuid=Generic Attribute handleStart=8 handleEnd=11> : Characteristic <Service Changed>, hnd=0x9, supports INDICATE Service <uuid=00001530-1212-efde-1523-785feabcd123 handleStart=30 handleEnd=65535> : Characteristic <00001532-1212-efde-1523-785feabcd123>, hnd=0x1f, supports WRITE NO RESPONSE Characteristic <00001531-1212-efde-1523-785feabcd123>, hnd=0x21, supports NOTIFY WRITE Characteristic <00001534-1212-efde-1523-785feabcd123>, hnd=0x24, supports READ -> '\x01\x00' Service <uuid=Battery Service handleStart=23 handleEnd=26> : Characteristic <Battery Level>, hnd=0x18, supports NOTIFY READ -> 'd' Service <uuid=Device Information handleStart=27 handleEnd=29> : Characteristic <Manufacturer Name String>, hnd=0x1c, supports READ -> 'Lezyne'
I have a fairly large photo collection on a raspberry pi based NAS. Unfortunately RPI ethernet port is not fast enough (100MB/s) for comfortable remote operation, so to be able to use that collection I have to keep local thumbnail directory on my linux box. Gnome nautilus is my tool of choice, but nautilus generates thumbnails only after entering a directory. To make that setup workable I had to:
1. Make sure gnome allows big thumbnails and doesn’t expire them: dconf-editor, go to org->gnome->desktop->thumbnail-cache and set maximum-age and maximum-size to -1
2. Generate the thumbnails
Nautilus thumbnails are saved in png files with name like this: 00067ecff5de0e48602327bc987f6d9a.png. The name is md5sum of image path with spaces replaced by %20. The path is not an absolute path in the system! So for example I have a photo at /run/user/1000/gvfs/sftp:host=192.168.1.231,user=pi/mnt/PhotoArchive/Dump/a_photo.jpg, but the path nautilus uses to generate thumbnail name is sftp://email@example.com/mnt/PhotoArchive/Dump/a_photo.jpg (it can be checked in nautilus – just right click on an image and check location). Local files have prefix file://
I had some problems with getting reliable results for a find command run on a remote system, so I decided to create 2 scripts to generate the thumbnails. The first script scans (scan.sh – BROKEN LINK) remote location for images, generates md5sum for the image path and, if there is no thumbnail stored locally, writes the file path to a pipe. Another script (thumbnail.sh –BROKEN LINK) waits for whatever shows up in the pipe and generates the thumbnail. An example usage:
./scan.sh /run/user/1000/gvfs/sftp:host=192.168.1.231,user=pi mnt/ sftp://firstname.lastname@example.org
and in a separate terminal:
./thumbnail.sh /run/user/1000/gvfs/sftp\:host\=192.168.1.231\,user\=pi/ sftp://email@example.com
/run/user/1000/gvfs/sftp\:host\=192.168.1.231\,user\=pi/ <– I have my NAS mounted at that point ($ROOT_DIRECTORY)
mnt/ <–the scripts scan should scan that directory and all subdirectories ($IMAGE_DIRECTORY)
sftp://firstname.lastname@example.org <– path prefix used by nautilius for that location to generate md5sum ($PREFIX)
I used those 2 script to generate over 65.000 (6 GB) of thumbnails. The directory where thumbnails are saved is hardcoded in thumbnail.sh (THUMBNAIL_DIR=/home/przemo/.cache/thumbnails/large/) – please update before using the script!
It’s a short guide to practical side of bluetooth LE using gatttool. How to read characteristics, turn on notifications and where to find more info about all those BLE numbers.
I was struggling for a while to read data from a BLE heart rate strap. It was working flawlessly with android apps, but I needed it to use it with raspberry pi and python. So, I had to dig a bit deeper under the surface of BLE. The results are below.
1. A computer with bluetooth v4.0 card or dongle
2. gatttool (part of bluez). Fedora users might have to compile bluez as there is no gatttool in bluez-5.23-1.fc21 bugreport: .
3. A BLE (bluetooth Low Energy, Bluetooth Smart) device – I use a Tacx heart rate belt 
An example command line session (red – important or info for later use, blue – value from previous steps, green – comment):
$ hciconfig hci0: Type: BR/EDR Bus: USB ^^ hci0: that's our hci device BD Address: C4:85:08:06:9F:C7 ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING PSCAN RX bytes:10243057 acl:34567 sco:0 events:5307 errors:0 TX bytes:46612 acl:737 sco:0 commands:2685 errors:0 fedora-lan:/home/przemo $ sudo hciconfig hci0 up fedora-lan:/home/przemo $ sudo hcitool -i hci0 lescan LE Scan ... <-- LE Scan was not showing anything, so Ctrl-C and hci0 reset ^Cfedora-lan:/home/przemo $ sudo hciconfig hci0 reset fedora-lan:/home/przemo $ sudo hcitool -i hci0 lescan LE Scan ... D6:90:A8:08:F0:E4 Tacx HRB 04741 ^^ D6:90:A8:08:F0:E4 that's BLE device address D6:90:A8:08:F0:E4 (unknown) D6:90:A8:08:F0:E4 Tacx HRB 04741 D6:90:A8:08:F0:E4 (unknown) ^Cfedora-lan:/home/przemo $ sudo gatttool -i hci0 -b D6:90:A8:08:F0:E4 -t random -I ^^ if you can't connect try to use "-t random" [D6:90:A8:08:F0:E4][LE]> connect Attempting to connect to D6:90:A8:08:F0:E4 Connection successful Reading value of battery level characteristic [D6:90:A8:08:F0:E4][LE]> primary attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x0011 uuid: 0000180d-0000-1000-8000-00805f9b34fb attr handle: 0x0012, end grp handle: 0x0015 uuid: 0000180f-0000-1000-8000-00805f9b34fb ^^^ 180f is "Battery Service", see link  attr handle: 0x0016, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb [D6:90:A8:08:F0:E4][LE]> characteristics 0x0012 0x0015 handle: 0x0013, char properties: 0x12, char value handle: 0x0014, uuid: 00002a19-0000-1000-8000-00805f9b34fb ^^ 2a19 is Battery Level, links  and  char properties 0x12: supports NOTIFICATION 0x10 and READ 0x02 (0x10 | 0x02 = 0x12) [D6:90:A8:08:F0:E4][LE]> char-read-hnd 0x0014 ^^ Reading handle value Characteristic value/descriptor: 64 ^^ value of battery level is 64, but it's hex, so 0x64 = 100. It's in %, link 
Reading heart rate [D6:90:A8:08:F0:E4][LE]> primary attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x0011 uuid: 0000180d-0000-1000-8000-00805f9b34fb ^^ 180d is "Heart Rate" service, link  attr handle: 0x0012, end grp handle: 0x0015 uuid: 0000180f-0000-1000-8000-00805f9b34fb attr handle: 0x0016, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb [D6:90:A8:08:F0:E4][LE]> characteristics 0x000c 0x0011 handle: 0x000d, char properties: 0x10, char value handle: 0x000e, uuid: 00002a37-0000-1000-8000-00805f9b34fb ^^ 2a37 is Heart Rate characteristic, links  and  char properties: 0x10: supports NOTIFICATION handle: 0x0010, char properties: 0x02, char value handle: 0x0011, uuid: 00002a38-0000-1000-8000-00805f9b34fb ^^ 2a38 is Body Sensor Location, links  and  char properties: 0x02: supports READ [D6:90:A8:08:F0:E4][LE]> char-read-hnd 0x0011 ^^ Reading Body Sensor Location Characteristic value/descriptor: 01 ^^ 0x01 it's "Chest", see link  for more options We need more info to switch on NOTIFICATION of heart rate [D6:90:A8:08:F0:E4][LE]> char-desc 0x000d 0x000f ^^ range of handles for heart rate: 0x000d is start of the range obtained with 'characteristics 0x000c 0x0011' 0x0010 is start of next characteristic minus 1: 0x0010 - 0x1 = 0x000f handle: 0x000d, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x000e, uuid: 00002a37-0000-1000-8000-00805f9b34fb handle: 0x000f, uuid: 00002902-0000-1000-8000-00805f9b34fb ^^ 2902 it is Client Characteristic Configuration, link  [D6:90:A8:08:F0:E4][LE]> char-write-cmd 0x000f 01 ^^ 01 comes from link , NOTIFICATIONS enabled Notification handle = 0x000e value: 00 3e <-- heart rate, 0x003e is 63 BPM Notification handle = 0x000e value: 00 3d <-- heart rate, 0x003d is 62 BPM Notification handle = 0x000e value: 00 3d <-- heart rate, 0x003d is 62 BPM Notification handle = 0x000e value: 00 3c <-- heart rate, 0x003c is 61 BPM [D6:90:A8:08:F0:E4][LE]> char-write-cmd 0x000f 00 ^^ 00 comes from link , NOTIFICATIONS disabled [D6:90:A8:08:F0:E4][LE]> disconnect <-- end of connection [D6:90:A8:08:F0:E4][LE]> fedora-lan:/home/przemo/android
MMA88451 doesn’t work with raspbterry pi out of the box. It needs I2C with repeated start. Test program in python:
import smbus DEVICE_ADDRESS = 0x1d MMA8451_REG_WHOAMI = 0x0D bus = smbus.SMBus(1) ret = bus.read_byte_data(DEVICE_ADDRESS, MMA8451_REG_WHOAMI) print ret
Shows zero instead of expected 26 (0x1A in hex)
pi@occberry ~/OpenCyclingComputer $ sudo python src/mma8451.py 0
Solution that I found here solves the problem:
sudo chmod 666 /sys/module/i2c_bcm2708/parameters/combined sudo echo -n 1 > /sys/module/i2c_bcm2708/parameters/combinedand now the python test code shows, as expected:
pi@occberry ~/OpenCyclingComputer $ sudo python src/mma8451.py 26