Hello there people of stackoverflow, I have created a control code to take input from two logitech extreme 3d pro joysticks and convert the data and then send that data to an arduino mega. The control code runs perfectly, however when I add the UI code (kivy based) to it the UI becomes non-responsive when the control code is running. I have tried threading the application, moving the control code to a separate file, and using kivy's included clock.schedule_interval function. None of these solutions seemed to work for me. I have included the .kv file, the main python file, and the control code file for you.
control code python file:
import pygame
import serial
import os, sys
import numpy as np
from threading import Thread
# function to map servo/motor data dependent on joystick input
def map(joy, min, max, omin, omax):
return float((((joy - min) * (omax - omin)) / (max - min)) + omin)
# same as above but used for the corner values of the joystick
def mapc(joy1, joy2, min1, max1, min2, max2, omin, omax):
return float((((((joy1 - min1) * (omax - omin)) / (max1 - min1)) + omin) + ((((joy2 - min2) * (omax - omin)) / (max2 - min2)) + omin)) / 2)
class JoysticksClass:
def __init__(self):
# Create the array with all the data
self.Data = [1500, 1500, 1500, 2200, 1500, 1500, 1500, 0]
# Create the arduino port
self.ard = serial.Serial('dev/ttyACM0', 230400, timeout = 0.01)
# Initialize pygame and the joysticks
pygame.init()
pygame.joystick.init()
# Connect the joysticks dumbfuck
# The while loop should only run if the joysticks arent connected
run = False
while run == False:
try:
self.Joy1 = pygame.joystick.Joystick(0)
self.Joy2 = pygame.joystick.Joystick(1)
except:
print("Connect the joysticks you dumb fuck")
time.sleep(5)
# Create the weights for turning and shit
self.x_weight = 0.4
self.y_weight = 0.4
self.z_height = 0.2
# Create the timer
self.Timer = 0
# This gathers the data from the joysticks
# DON'T FUCK WITH IT
def JoyRead(self):
self.Joy1X = self.Joy1.get_axis(0)
self.Joy1Y = self.Joy1.get_axis(1)
self.Joy1Z = self.Joy1.get_axis(2)
self.Joy1S = self.Joy1.get_axis(3)
self.Joy1B1 = self.Joy1.get_button(0)
self.Joy1B3 = self.Joy1.get_button(2)
self.Joy1B6 = self.Joy1.get_button(5)
self.Joy1B7 = self.Joy1.get_button(6)
self.Joy1B8 = self.Joy1.get_button(7)
self.Joy1B9 = self.Joy1.get_button(8)
self.Joy1B10 = self.Joy1.get_button(9)
self.Joy2X = self.Joy2.get_axis(0)
self.Joy2Y = self.Joy2.get_axis(1)
self.Joy2Z = self.Joy2.get_axis(2)
self.Joy2S = self.Joy2.get_axis(3)
self.Joy2B1 = self.Joy2.get_button(0)
self.Joy2B3 = self.Joy2.get_button(2)
self.Joy2B5 = self.Joy2.get_button(4)
self.Joy1H = self.Joy1.get_hat(0)
def JoyConv(self):
# Horizontal Movement
x_movement = self.Joy1X * 1
y_movement = self.Joy1Y * -1
z_movement = self.Joy1Z * 1
# Deadzones
if x_movement > -0.1 and x_movement < 0.1:
x_movement = 0
if y_movement > -0.1 and y_movement < 0.1:
y_movement = 0
if z_movement > -0.1 and z_movement < 0.1:
z_movement = 0
M1 = ((x_movement * self.x_weight) + (y_movement * self.y_weight) + (-z_movement * self.z_weight))
M2 = ((-x_movement * self.x_weight) + (y_movement * self.y_weight) + (z_movement * self.z_weight))
self.Data[0] = map(M1, -0.8, 0.8, 1000, 2000)
self.Data[1] = map(M2, -0.8, 0.8, 1000, 2000)
# Vertical movement
self.Data[2] = map(self.Joy1S, -1, 1, 1000, 2000)
# S1 = Tilt
if round(map(self.Joy2Y, -1, 1, 1000, 2200)) > 1600 and self.S1_Data < 2200 and self.Timer % 50 == 0:
self.Data[3] = self.Data[3] + 7
elif round(map(self.Joy2Y, -1, 1, 1000, 2200)) < 1400 and self.S1_Data > 1000 and self.Timer % 50 == 0:
self.Data[3] = self.Data[3] - 7
else:
self.Data[3] = self.Data[3]
# S2 = Twist
self.Data[4] = map(self.Joy2X, -1, 1, 1000, 2000)
# S3 = Claw
self.Data[5] = map(self.Joy2S, -1, 1, 1000, 1800)
# S4 = Camera
if self.Joy1H == (0, -1) and self.Data[6] <= 2200 and self.Timer % 10 == 0:
self.Data[6] = self.Data[6] + 5
elif self.Joy1H == (0, 1) and self.Data[6] >= 800 and self.Timer % 10 == 0:
self.Data[6] = self.Data[6] - 5
else:
self.Data[6] = self.Data[6]
# Lights
if self.Joy1H == (1, 0) and self.Timer % 5 == 0:
self.Data[7] = 1
if self.Joy1H == (-1, 0) and self.Timer % 5 == 0:
self.Data[7] = 0
# Increment the timer
self.Timer = self.Timer + 1
# Send the data to the arduino
def STA(self):
MotorData = str(self.Data)
MotorData = MotorData.replace('[', '')
MotorData = MotorData.replace(']', '\n')
DataByteArray = bytearray(MotorData, 'ascii')
if self.ard.inWaiting():
self.ard.write(DataByteArray)
data = self.ard.readline()
print(MotorData, data)
main python file:
import control_code
# Call all the kivy dependent functions and libraries
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.graphics.texture import Texture
from kivy.lang import Builder
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty, NumericProperty
# Define the main class to run everything else
class Main(GridLayout):
def start_Press(self):
self.joy = control_code.JoysticksClass()
Clock.schedule_interval(Control(), 0.001)
def Transect_Press(self):
return 0
def Subway_Press(self):
return 0
def Mussels_Press(self):
return 0
def ImageRec_Press(self):
return 0
def Control(self):
self.joy.JoyRead()
self.joy.JoyConv()
self.joy.STA()
print(self.joy.Data)
def Transect(self):
return 0
def Subway(self):
return 0
def Mussels(self):
return 0
def ImageRec(self):
return 0
class MainClass(App):
def build(self):
self.load_kv('main.kv')
return Main()
if __name__ == '__main__':
MainClass().run()
and the kv file that goes with it:
rows: 2
cols: 1
GridLayout:
rows: 1
cols: 2
size_hint: 1, 1
Button:
text: "Autonomous Output Place Holder"
GridLayout:
rows: 4
cols: 1
size_hint: 0.3, 1
Button:
text: "Start Button"
on_release: root.start_Press()
Button:
text: "Start Transect Line"
on_release: root.Transect_Press()
Button:
text: "Start Subway Car"
on_release: root.Subway_Press()
Button:
text: "Start Vision Recognition"
on_release: root.Mussels_Press()
GridLayout:
rows: 1
cols: 2
size_hint: 1, 0.3
Button:
text: "Diagnostic Panel"
Button:
text: "Stop Button"
size_hint: 0.3, 1
on_release: exit()
Any help as always would be very helpful. Also my apologies if the code isn't formatted the way it is supposed to be