0

I have connected a button to the GPIO on my raspberry Pi and I have tested it; it works. I have used the following code:

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(16,GPIO.IN)

finally:

GPIO.cleanup()

All I want is for that button to imitate a left mouse click. So that when it is pressed the pi thinks i have left clicked on the mouse.

Any help would be appreciated.

Md. Rezwanul Haque
  • 2,882
  • 7
  • 28
  • 45
James Novis
  • 343
  • 5
  • 15

3 Answers3

3

for mouse control, these posts can help you:

For GPIO manipulation, see this example on e-linux

You first need to monitor the state changes on the GPIO pin your button is wired to. (i.e. put it in a loop)

Then when it changes, call a function which role is to send a mouse click.
To do so, try using PyUserInput. (on the getting started part, there is an example doing a mouse click on the center of the screen).

peyo
  • 442
  • 3
  • 9
  • I have looked at both but none tell me how to make my push button register as a mouse click – James Novis Aug 17 '17 at 19:18
  • 1
    well, you have to read (in a loop) your gpio state *the one with the button) and send a click through the post I've mentioned. – peyo Aug 17 '17 at 19:24
  • sorry dude. I'm a newbie and kinda need someone to tell me how to do it rather than pointing me at other articles which really don't answer the question. – James Novis Aug 17 '17 at 20:00
  • 1
    I just did tell you.. make a loop reading the GPIO state on youtrbutton. When it (the GPIO state) changes, use one of the way pointed in the linked stackoverflow questions above to simulate the click. I'm sorry but it's pretty straightforward, no? – peyo Aug 17 '17 at 20:04
  • For you maybe but for me no. – James Novis Aug 17 '17 at 20:10
  • I have made a loop, I have now got the raspberry pi to recognise the input on pin 16, but I can find nowhere that converts pin 16 into a mouse click. – James Novis Aug 17 '17 at 20:11
  • You cannot "convert" pin16 into a mouse-click, but you can use a python module to send a mouse click. For instance, when the GPIO pin state changes, call a function which will send a mouse click. From the second link of this post, see https://github.com/SavinaRoja/PyUserInput (the getting started part, there is a mouse click at the center of screen example) You'll be needing `PyUserInput` available from `pip` for python2 and python3. – peyo Aug 17 '17 at 20:17
1

So I only needed my GPIO button on pin 16 to left click a mouse button on a certain area of the screen so that I could activate an app without the Pi connected with HDMI or to a wireless keyboard.

I installed pyuserinput then used the following code:

importRPI.GPIO as GPIO
import time

from pymouse import PyMouse
m = PyMouse()

GPIO.setmode(GPIO.BOARD)
GPIO.setup(16,GPIO.IN)

try:
   while True:
       if GPIO.input(16)!=0:m.click(300,275,1)
       time.sleep(0.2)

finally:
    GPIO.cleanup()

Through trial and error I found the right coordinates (300,275) and the 1 indicated left mouse click. I tried playing with the sleep settings to stop repeat registering of the inputted button. sleep 0.2 worked best.

James Novis
  • 343
  • 5
  • 15
  • To avoid the repetition problem, you can look for `debounce`. You can also have a record of the previous state, thus allowing you to do the mouse click only on GPIO state change. – peyo Aug 17 '17 at 22:49
0

To improve efficieny, I used an example on Raspi-TV. Also, link to the latest version of what is now pynput for mouse/keyboard input.

It uses interrupts rather than a timer. I did something very similar for 6 buttons connected to GPIO pins. Each button simulates a mouse click at a different point on the screen. This is what it would look like for your example.

I utilized GPIO 1 as an interrupt to the program. In my case, I don't use GPIO 1, and I wanted the program to continue to run indefinitely. However, you could hook another button up to that, or create a piece of code that would change the state from 0 to 1 to stop the script below. RPi.GPIO runs all of the detection triggers in a single thread, so the below script will continue to run until GPIO 1 in this case experiences a rising edge. I believe that would be lower overhead than freezing the thread for a timer every 0.2 seconds.

from pynput.mouse import Button, Controller
import RPi.GPIO as GPIO
import time

mouse = Controller()

GPIO.setmode(GPIO.BCM)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

GPIO.setup(1,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

def GB1(channel):
    print(f"Detected Left Most Green Button on {channel}")
    mouse.position  = (300,275)
    mouse.press(Button.left)
    mouse.release(Button.left)
   
GPIO.add_event_detect(16,GPIO.RISING, callback=GB1, bouncetime=200)

try:
    print("Waiting...")
    
    GPIO.wait_for_edge(1, GPIO.RISING)
    print("Time's up..")
except:
    print("Exception, exiting.")
    GPIO.cleanup()
finally:
    print("Normal Program Exit.")
    GPIO.cleanup()