Crawler

A colleague who works at Astro Designs and who I know from the Cotswold Raspberry Jam sent me his beta version of a Pi-Zero motor controller.  Since it was raining all weekend, and I’ve run out of stuff to do with Chloe and Zoe until Scance Sweep from Kickstarter appears, I decided to build and play with it.  I think it’s really cute (sorry about the blurred photo, no idea why since the camera was on a tripod).

Crawler

Crawler

It runs a python script at boot time, which polls for a Wii NumChuck bluetooth controller using the cwiid python library which is included in the Raspian Jessie-lite distribution.  Once joined, the buttons on the NumChuck control the movement of the robot, and also provide a safe shutdown at the end.  Or in theory, that’s how it will work.

The frame and motors are from pimoroni.  It’s powered by 4 AA batteries, with a LDO 5V regulator powering the Pi Zero.

The only problem I have is getting the CWiiD python library to connect to  the Raspian bluetooth driver.  For some reason, bluetooth hates me – I’ve binned several sets of keyboards and mice over the years as they either fail to connect, or forever keep dropping out on my windows desktop.

And that hatred continue – the simple test code below which has worked for others, fails completely returning “Socket connect error (control connection)”.  Google reports lots of historic occurrences but no solutions.

#!/usr/bin/env python2.7

import RPi.GPIO as GPIO # Import the GPIO Library
import cwiid
import time
import os


# Set the GPIO modes
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Set variable for the LED pin
pinLED1 = 5
pinLED2 = 6

# Set the LED Pin mode to be Output
GPIO.setup(pinLED1, GPIO.OUT)
GPIO.setup(pinLED2, GPIO.OUT)

try:
   do_WiiRemote()
except KeyboardInterrupt:
   GPIO.cleanup()
         

def do_WiiRemote():
   #connecting to the wiimote. This allows several attempts
   # as first few often fail.
   print 'Press 1+2 on your Wiimote now...'
   wm = None
   i=1
   while not wm:
      try:
         for x in range(0,i):
            GPIO.output(pinLED1, True)
            time.sleep(0.5)
            GPIO.output(pinLED1, False)
            time.sleep(0.5)
         GPIO.output(pinLED1,True)
         print "Bluetooth pairing attempt " + str(i)

         wm=cwiid.Wiimote()
      except RuntimeError:
         if (i>10):
            print("cannot create connection")
            quit()
         print "Error opening wiimote connection"
         i +=1

   GPIO.output(pinLED1, False)

   #set wiimote to report button presses and accelerometer state
   wm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_ACC

   #turn on led to show connected
   wm.led = 1

   buttons = wm.state['buttons']
   speed = 100

   while not(buttons == 140):
      buttons = wm.state['buttons']
      print("Buttons: " + str(buttons))
      time.sleep(0.2)

   GPIO.cleanup()

I am seriously p’d off – this was meant to be a quick 1 day project for a diversion from the Quadcopter stuff, but now it’s become a PITA in its own right.  I suspect it’s the bluetooth daemon in Jessie that’s refusing the connection from cwiid, and that means there’s not a lot I can do about it.


I’m going to track my investigations here.

The cwiid error is triggered here in cwiid-master/libcwiid/connect.c

	/* Connect to Wiimote */
	/* Control Channel */
	memset(&remote_addr, 0, sizeof remote_addr);
	remote_addr.l2_family = AF_BLUETOOTH;
	remote_addr.l2_bdaddr = *bdaddr;
	remote_addr.l2_psm = htobs(CTL_PSM);
	if ((ctl_socket =
	  socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) {
		cwiid_err(NULL, "Socket creation error (control socket)");
		goto ERR_HND;
	}
	if (connect(ctl_socket, (struct sockaddr *)&remote_addr,
		        sizeof remote_addr)) {
		cwiid_err(NULL, "Socket connect error (control socket)");
		goto ERR_HND;
	}

	/* Interrupt Channel */
	remote_addr.l2_psm = htobs(INT_PSM);
	if ((int_socket =
	  socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) {
		cwiid_err(NULL, "Socket creation error (interrupt socket)");
		goto ERR_HND;
	}
	if (connect(int_socket, (struct sockaddr *)&remote_addr,
		        sizeof remote_addr)) {
		cwiid_err(NULL, "Socket connect error (interrupt socket)");
		goto ERR_HND;
	}

	if ((wiimote = cwiid_new(ctl_socket, int_socket, flags)) == NULL) {
		/* Raises its own error */
		goto ERR_HND;
	}

	return wiimote;

ERR_HND:
	/* Close Sockets */
	if (ctl_socket != -1) {
		if (close(ctl_socket)) {
			cwiid_err(NULL, "Socket close error (control socket)");
		}
	}
	if (int_socket != -1) {
		if (close(int_socket)) {
			cwiid_err(NULL, "Socket close error (interrupt socket)");
		}
	}
	return NULL;
}

I need to dig further as to why the socket to the bluetooth daemon / driver failed.


A more precise google search turned up a Bluetooth kernel driver problem – perhaps this is it?

Leave a Reply

Your email address will not be published. Required fields are marked *