Dank
Posts: 1
Joined: Tue Oct 17, 2017 9:01 am

Joystick und Rotary Encoder zusammen nutzen

Tue Oct 24, 2017 8:23 am

Hi liebe Community,


Ich stelle mich grad ziemlich blöd an, ich versuche ein Programm zu erstellen das die Werte eines Analog Joysticks und die Werte eines Encoders ausliest.

Jeweils einzeln habe ich diese Programme schon und sie Funktionieren. Doch sobald ich diese zusammenfüge kriege ich bei mir immer das reinste chaos raus. Entweder es gibt mir immer nur die werte von einem Bauteil raus oder der Raspi hängt sich auf.


ich bin auch für Tipps dankbar.


Gruss Dani


Das Encoder Programm ist von: https://www.sunfounder.com/learn/Super_ ... rrypi.html

Das Joystick Programm ist von: https://www.raspberrypi-spy.co.uk/2014/ ... n-mcp3008/


Code vom Analog Joystick:

Code: Select all

# This script reads data from a 
# MCP3008 ADC device using the SPI bus.
#
# Analogue joystick version!
#
#--------------------------------------

import spidev
import time
import os

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)

# Define sensor channels
# (channels 3 to 7 unused)
swt_channel = 0
vrx_channel = 1
vry_channel = 2

# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7
def ReadChannel(channel):
  print (channel)
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  #print (channel)
  return data
 

# Define delay between readings (s)
delay = 0.25

while True:

  # Read the joystick position data
  vrx_pos = ReadChannel(vrx_channel)
  vry_pos = ReadChannel(vry_channel)

  # Read switch state
  swt_val = ReadChannel(swt_channel)

  # Print out results
  print ("--------------------------------------------")  
  print("X : {}  Y : {}  Taster : {}".format(vrx_pos,vry_pos,swt_val))

  # Wait before repeating loop
  time.sleep(delay)
Code vom Encoder:

Code: Select all

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

RoAPin = 11    # pin11
RoBPin = 12    # pin12
RoSPin = 15    # pin13

globalCounter = 0

flag = 0
Last_RoB_Status = 0
Current_RoB_Status = 0

def setup():
	GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
	GPIO.setup(RoAPin, GPIO.IN)    # input mode
	GPIO.setup(RoBPin, GPIO.IN)
	GPIO.setup(RoSPin,GPIO.IN,pull_up_down=GPIO.PUD_UP)
	rotaryClear()

def rotaryDeal():
	global flag
	global Last_RoB_Status
	global Current_RoB_Status
	global globalCounter
	Last_RoB_Status = GPIO.input(RoBPin)
	while(not GPIO.input(RoAPin)):
		Current_RoB_Status = GPIO.input(RoBPin)
		flag = 1
	if flag == 1:
		flag = 0
		if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
		    globalCounter = globalCounter + 1
		    print (globalCounter)
		if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
		    globalCounter = globalCounter - 1
		    print(globalCounter)


def rotaryClear():
        GPIO.add_event_detect(RoSPin, GPIO.FALLING, callback=clear) # wait for falling

def clear(ev=None):
        globalCounter = 0
        print(globalCounter)
        time.sleep(1)




def loop():
	global globalCounter
	while True:
		rotaryDeal()
#		print 'globalCounter = %d' % globalCounter

def destroy():
	GPIO.cleanup()             # Release resource

if __name__ == '__main__':     # Program start from here
	setup()
	try:
		loop()
	except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
		destroy()



Zu guter letzte Mein selbst erstellter Code:

Meine Gedanken dazu:
Ich Held hab einen ewig langen Text geschrieben und dann ausversehentlich alles gelöscht... kurz zusammengefasst Mein gedanke war wenn ich die beiden While True Schleifen der Beiden Programme zusammenfüge so arbeiten sich beide Programme ab und geben mir sowohl Encoder als auch Joystick Werte aus bis in alle Ewigkeit.


In Wirklichkeit aber hängt sich der Pi fasst auf und gibt verzögert nur die joystick werte.

Code: Select all

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
import spidev
import os

RoAPin = 11    # pin11
RoBPin = 12    # pin12
RoSPin = 15    # pin13

globalCounter = 0

flag = 0
Last_RoB_Status = 0
Current_RoB_Status = 0

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)

# Define sensor channels
# (channels 3 to 7 unused)
swt_channel = 0
vrx_channel = 1
vry_channel = 2

# Define delay between readings (s)
delay = 0.25



#//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
def setup():
	GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
	GPIO.setup(RoAPin, GPIO.IN)    # input mode
	GPIO.setup(RoBPin, GPIO.IN)
	GPIO.setup(RoSPin,GPIO.IN,pull_up_down=GPIO.PUD_UP)
	rotaryClear()

def rotaryDeal():
	global flag
	global Last_RoB_Status
	global Current_RoB_Status
	global globalCounter
	Last_RoB_Status = GPIO.input(RoBPin)
	while(not GPIO.input(RoAPin)):
		Current_RoB_Status = GPIO.input(RoBPin)
		flag = 1
	if flag == 1:
		flag = 0
		if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
		    globalCounter = globalCounter + 1
		    print (globalCounter)
		if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
		    globalCounter = globalCounter - 1
		    print(globalCounter)


def rotaryClear():
        GPIO.add_event_detect(RoSPin, GPIO.FALLING, callback=clear) # wait for falling

def clear(ev=None):
        globalCounter = 0
        print(globalCounter)
        time.sleep(1)

def ReadChannel(channel):
  print (channel)
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  #print (channel)
  return data


def loop():
	global globalCounter
	while True:
		rotaryDeal()
		#ab hier würden aus Zwei Wihile true Schleifen eine.
		vrx_pos = ReadChannel(vrx_channel)
		vry_pos = ReadChannel(vry_channel)
		swt_val = ReadChannel(swt_channel)
		print ("--------------------------------------------")
		print("X : {}  Y : {}  Taster : {}".format(vrx_pos,vry_pos,swt_val))
		#time.sleep(1)
                
                
#		print 'globalCounter = %d' % globalCounter

def destroy():
	GPIO.cleanup()             # Release resource

if __name__ == '__main__':     # Program start from here
	setup()
	try:
		loop()
	except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
		destroy()


User avatar
mline
Posts: 1424
Joined: Sun Jan 27, 2013 1:47 pm
Location: Austria, Vienna

Re: Joystick und Rotary Encoder zusammen nutzen

Tue Oct 24, 2017 9:57 am

Hast du nen Manual für dein Rotary Switch? Die sind oft sehr Abenteuerlich beschalten und ich vermute den Fehler beim Anschluss und der Pinkonfiguration. Oder hast du dir dieses Set von dem Shop da geholt?

Eventuell blockiert auch diese Zeile in der Funktion rotaryDeal()

Code: Select all

while(not GPIO.input(RoAPin)):
Bin mir aber nicht sicher weil ich nicht ganz schnall welchen Wert der Encoder im Ruhezustand hat (bin auch schon etwas müde, lange Nacht gehabt :D ), außerdem ist python nicht so mein Ding. Kanns zwar lesen aber is wie mit ner Fremdsprache die man nicht so gut kann

Was noch problematisch ist: Rotary Encoder sind sehr zeitkritisch und damit ist Polling zwar möglich aber wird sehr schnell an die Grenzen kommen.
Denk drann das du kein RealTimeOS (oder nen Arduino etc.) benutzt. Wenn die CPU belegt ist wird der Wert eventuell zu spät gelesen.
Ich würd da eher mit Interrupts arbeiten.

btw... ich find python ist echt hässlicher code ;)
<~~>

smartifahrer
Posts: 1038
Joined: Sat Feb 13, 2016 8:10 am

Re: Joystick und Rotary Encoder zusammen nutzen

Tue Oct 24, 2017 12:33 pm

Ich sehe es wie mline. Solange der Code-Teil des Rotary Encoder kein Ergebnis liefert (blockiert durch while(not GPIO.input(RoAPin)):) verbleibt das Script in der while Schleife. Das sieht dann so aus als ob es abgestürzt ist. Da du erst danach die Joytickwerte ausgibt werden dies scheinbar verzögert ausgegeben. Letztlich musst du sehen wie du, z.B. per Interrupt Verarbeitung (Interrupt-Handler), das auslesen des Rotary Encoder aus der Schleife in loop() bekommst. Innerhalb der Schleife greift du dann auf den zwischengespeicherten Wert des Interrupt-Handlers zu.

Return to “Deutsch”