Web UI + web cam

Hi, By following the various post on the forum I've managed to use the web ui without the camera. I'm now wondering if it is possible to use a usb web camera in place of the standard raspberry camera.

Also how can I modify the code so that when a button is pressed the motors run and only stop or change direction when another button is pressed.


piborg's picture

As long as the web camera supports Video4Linux the script can be altered to work with it.
This requires a fair number of changes though as the current script makes use of the picamera library which only supports the standard camera.

As for the buttons this feature is already present, how the buttons behave depends which URL you go to.
If we assume the Pi has an IP address of then:

  • - Buttons need to be held down to keep moving
  • - Buttons keep moving until a different button is pressed


I've just tested this feature. It does work as explained, however, no matter for how long you press forward, for example, somehow it still goes forward only a set amount of time, eventhough I'm still holding the button with my mouse.
Is there a way for the robot to really go forward for as along as I hold the button down?


piborg's picture

The most likely cause is the disconnected check is shutting the motors down. It basically works by checking how long it has been since a button has been pressed or the camera image has been updated. If the image is updating too slowly it may be causing it to trigger.

This is the code responsible for the disconnection check:

# Timeout thread
class Watchdog(threading.Thread):
    def __init__(self):
        super(Watchdog, self).__init__()
        self.event = threading.Event()
        self.terminated = False
        self.timestamp = time.time()

    def run(self):
        timedOut = True
        # This method runs in a separate thread
        while not self.terminated:
            # Wait for a network event to be flagged for up to one second
            if timedOut:
                if self.event.wait(1):
                    # Connection
                    print 'Reconnected...'
                    timedOut = False
                if self.event.wait(1):
                    # Timed out
                    print 'Timed out...'
                    timedOut = True

What you can do is increase the allowed time to be greater than one second. To do this you need to change the number in the lines:

if self.event.wait(1):

to something larger, 5 for example:

if self.event.wait(5):

Hopefully this will solve the problem :)

Thanks, this did solve the problem. Just for a safe measure, I've changed from 1s to 10s just so if I wanted to drive in a straight line without stoping for longer periods of time:)

Ive had great fun controlling a robot using the web UI. Your advice has been amazing. Thanks.

I would now like to use my piborg reverse to power a ROV. It would need three motors and therefore will need a second reverse. Two motors will control forward/reverse and left/right, the third motor would control ascend/ descend. I would like to continue using the Web UI as it has the option for using a camera. When adding the second reverse board would extra controls show up on the Web UI ? If not would it be possible (and how) to add controls for the third motor I.e ascend/ descend.
Edit. After much head scratching and searching I've got a possible solution but also a problem! Would it be possible to add a second piborg reverse and control three motors with the joyborg script ? Again would this be possible and how?

Thanks in advance.

piborg's picture

The first thing to do is setup the two boards with different addresses. Follow this detailed guide: Setting up multiple PicoBorg Reverses

In the below code I will be using the addresses 0x11 and 0x12. If you used different ones change the numbers as needed. The board with address 0x11 is for the left / right motors as normal.

The next step is to get the first board working again at the new address. Open the diddyJoy.py script and find this line:

#PBR.i2cAddress = 0x44                  # Uncomment and change the value if you have changed the board address

Change the line to remove the comment symbol and use the new number like so:

PBR.i2cAddress = 0x11

At this stage you should be able to save the script and it should work the same as before.

Next we will add a new section to setup the second PicoBorg Reverse as PBR2. Add this after the setup of the first board:

# Setup PicoBorg Reverse #2
PBR2 = PicoBorgRev.PicoBorgRev()
PBR2.i2cAddress = 0x12
if not PBR2.foundChip:
    boards = PicoBorgRev.ScanForPicoBorgReverse()
    if len(boards) < 2:
        print 'Second PicoBorg Reverse not found, check you are attached :)'
        print 'No PicoBorg Reverse at address %02X, but we did find two boards:' % (PBR2.i2cAddress)
        for board in boards:
            print '    %02X (%d)' % (board, board)
        print 'If you need to change the I²C address change the setup line so it is correct, e.g.'
        print 'PBR2.i2cAddress = 0x%02X' % (boards[0])
#PBR2.SetEpoIgnore(True)                 # Uncomment to disable EPO latch, needed if you ...
# Ensure the communications failsafe has been enabled!
failsafe = False
for i in range(5):
    failsafe = PBR2.GetCommsFailsafe()
    if failsafe:
if not failsafe:
    print 'Board %02X failed to report in failsafe mode!' % (PBR2.i2cAddress)

Now we need to add a third joystick axis to read. I will used axis 3 which is up and down on the right stick for a PS3 controller. Start by adding a new setting for the control:

# Settings for the joystick
axisUpDown = 1                          # Joystick axis to read for up / down position
axisUpDownInverted = False              # Set this to True if up and down appear to be swapped
axisLeftRight = 2                       # Joystick axis to read for left / right position
axisLeftRightInverted = False           # Set this to True if left and right appear to be swapped
axisThird = 2                           # Joystick axis to read for the third motor
axisThirdInverted = False               # Set this to True if the third motor appears to be swapped
buttonResetEpo = 3                      # Joystick button number to perform an EPO reset (Start)
buttonSlow = 8                          # Joystick button number for driving slowly whilst held (L2)
slowFactor = 0.5                        # Speed to slow to when the drive slowly button is held, ...
buttonFastTurn = 9                      # Joystick button number for turning fast (R2)
interval = 0.00                         # Time between updates in seconds, smaller responds faster ...

After that add a new value, thirdMotor:

    print 'Press CTRL+C to quit'
    driveLeft = 0.0
    driveRight = 0.0
    running = True
    hadEvent = False
    upDown = 0.0
    leftRight = 0.0
    thirdMotor = 0.0
    # Loop indefinitely

The next part is to read the third joystick position:

                # Read axis positions (-1 to +1)
                if axisUpDownInverted:
                    upDown = -joystick.get_axis(axisUpDown)
                    upDown = joystick.get_axis(axisUpDown)
                if axisLeftRightInverted:
                    leftRight = -joystick.get_axis(axisLeftRight)
                    leftRight = joystick.get_axis(axisLeftRight)
                if axisThirdInverted:
                    thirdMotor = -joystick.get_axis(axisThird)
                    thirdMotor = joystick.get_axis(axisThird)
                # Apply steering speeds

Now add the third motor output to the slow check and setting of the motor speeds by adding these lines:

                # Determine the drive power levels
                driveLeft = -upDown
                driveRight = -upDown
                driveThird = thirdMotor
                if leftRight < -0.05:
                    # Turning left
                    driveLeft *= 1.0 + (2.0 * leftRight)
                elif leftRight &rt; 0.05:
                    # Turning right
                    driveRight *= 1.0 - (2.0 * leftRight)
                # Check for button presses
                if joystick.get_button(buttonResetEpo):
                if joystick.get_button(buttonSlow):
                    driveLeft *= slowFactor
                    driveRight *= slowFactor
                    driveThird *= slowFactor
                # Set the motors to the new speeds
                PBR.SetMotor1(driveRight * maxPower)
                PBR.SetMotor2(-driveLeft * maxPower)
                PBR2.SetMotor1(driveThird * maxPower)

Finally find all copies of:


and add the same for the second board:


There should be three in the standard example.

Thanks for the above, I'm waiting for payday so I can buy my second reverse. I modified the code/ axis so have forward/ reverse/ left right on one joystick. I've tested this wit the diddyjoy script and works great. However........

To control the "ROV" remotely I will need a tether. I considered using usb-to- cat5 adaptors. With these I could simply plug the game pad in and use the diddyjoy script.
I would prefer however to plug the cat5 network cable directly to the Raspbery Pi and connect it to a second Raspberry pi. this would enable me to make any adjustments to the ROV using VNC and I could make use of the Remote joy script.
I've spent all weekend trying to get the remote joy to work. Nothing I try works.
Ive followed the instructions and all works on the controlling Pi but not on the Pi conected to the picoborg.
Is there an updated method of using the diddy joy as a remotejoy.
Also how would I run this on start up.

Thanks again for all your help.

piborg's picture

RemoteJoy is a bit of an old example, it was intended for our PiCy kit which did not really have any speed control. As such the scripts would need a fair bit of editing to make them work correctly with a PicoBorg Reverse instead.

What you will need to do is take the RemoteKeyBorgS.py script and change it to control the PicoBorg Reverse instead. The messages sent over the network will probably need to be changed as well, this will affect the scripts at both ends.

Once again your advice has been second to none. Just a quick update. I purchased usb-Cat5 adaptors and am now able to control my motors with a joystck from a distance of over 50 feet. Result !
I need a bit more advice. I would like to be able to use a button on the joystick to turn on a set of LED's or latch a relay. Using the remoteJoy code is it possible to do this directly or would I need to use one of the GPIO pins ?
If so how would change the code?
thanks in advance.

piborg's picture

You should be able to use the RemoteJoyBorg code to do this, it controls GPIO pins by default anyway.

If you look at the standard joystick example for DiddyBorg there is some code which looks for button presses on the joystick which you can copy into the existing for event in events: loop.

What you then need to do is add a new value into the driveCommands list for the extra function at both ends, the standard ON / OFF values should be fine for what you will need :)

Subscribe to Comments for &quot;Web UI + web cam&quot;