Go Down

Topic: help with Python with USB joystick controlling servo and dc motor with PWM? (Read 3690 times) previous topic - next topic

amanmazleifg

Alright to summarise about the project I intend to build on with my Arduino. I'm planning to build an unmanned ground vehicle that will be controlled wireless using the Xbee modules, a computer, a Logitech Attack 3 and lastly, the ever important Python. I had figured out some codes but right now, I have trouble figuring out how to make sure my servo moves as long as I press down the button on the joystick. Its frustrating that I have to keep pressing and (un)pressing the joystick buttons to move the servo. Can anyone help me figure out how to make sure the servo can move as long as I keep the buttons down? And also can anyone guide me about how I can use the analog stick to control motors with PWM? For example, when I move the joystick forwards, two motors will rotate clockwise and when i move the joystick to the left or right, one motor will move forwards and another backwards. And as a bonus if I move the joystick diagonally, one motor will maintain speed/increase speed and the other lower speed/maintain speed? Thanks guys!

Here are my codes.
Python code for joystick event control.
Code: [Select]
#!/usr/bin/env python

################################################################
# Module:   multijoystick.py
# Created:  2 April 2008
# Author:   Brian D. Wendt
#   http://principialabs.com/
# Version:  0.2
# License:  GPLv3
#   http://www.fsf.org/licensing/
'''
Provides four-axis joystick servo control from a PC
using the Arduino "MultipleServos" sketch
and the Python "servo.py" serial abstraction module.

Parts of this code were adapted from:
 http://svn.lee.org/swarm/trunk/mothernode/python/multijoy.py

NOTE: This script requires the following Python modules:
 pyserial - http://pyserial.sourceforge.net/
 pygame   - http://www.pygame.org/
 servo    - http://principialabs.com/
Win32 users may also need:
 pywin32  - http://sourceforge.net/projects/pywin32/
'''
################################################################

import servo
import pygame

# allow multiple joysticks
joy = []

# handle joystick event
def handleJoyEvent(e):
   #if e.type == pygame.JOYAXISMOTION:
       #axis = "unknown"
       #if (e.dict['axis'] == 0):
           #axis = "X"

       #if (e.dict['axis'] == 1):
           #axis = "Y"

       #if (e.dict['axis'] == 2):
           #axis = "Throttle"

       #if (e.dict['axis'] == 3):
           #axis = "Z"

       #if (axis != "unknown"):
           #str = "Axis: %s; Value: %f" % (axis, e.dict['value'])
           # uncomment to debug
           #output(str, e.dict['joy'])

           # Arduino joystick-servo hack
           #if (axis == "X"):
               #pos = e.dict['value']
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               #servo.move(1, serv)

           # Arduino joystick-servo hack
           #if (axis == "Y"):
               #pos = e.dict['value']
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               #servo.move(2, serv)

           # Arduino joystick-servo hack
           #if (axis == "Z"):
               #pos = e.dict['value']
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               #servo.move(3, serv)

           # Arduino joystick-servo hack
           #if (axis == "Throttle"):
               #pos = e.dict['value']
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               #servo.move(4, serv)

   if e.type == pygame.JOYBUTTONDOWN:
       str = "Button: %d" % (e.dict['button'])
       # uncomment to debug
       # uncomment to debug
       output(str, e.dict['joy'])
       # Button 8 to quit
       
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#=========================Rifle control section========================
#-------------------------Axis Y---------------------------------------
       if (e.dict['button'] == 1):
               #serv = 1
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               servo.move(1, 0)
       if (e.dict['button'] == 2):
               #serv = 1
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               servo.move(1, 1)
#----------------------------------------------------------------------
#-------------------------Axis X---------------------------------------
       if (e.dict['button'] == 3):
               #serv = 1
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               servo.move(3, 3)
       if (e.dict['button'] == 4):
               #serv = 1
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               servo.move(3, 4)      
#======================================================================
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#========================Rifle cocking section=========================
       for serv in range(0, 180, 1):
           if (e.dict['button'] == 5):
               #serv = serv + 1
               # convert joystick position to servo increment, 0-180
               #move = round(pos * 90, 0)
               #serv = int(90 + move)
               # and send to Arduino over serial connection
               servo.move(12, serv)
#======================================================================
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#========================Program Exit==================================
       if (e.dict['button'] == 7):
           print "Mission End"
           quit()
#======================================================================
   else:
       pass

# print the joystick position
def output(line, stick):
   print "Joystick: %d; %s" % (stick, line)

# wait for joystick input
def joystickControl():
   while True:
       e = pygame.event.wait()
       if (e.type == pygame.JOYAXISMOTION or e.type == pygame.JOYBUTTONDOWN):
           handleJoyEvent(e)

# main method
def main():
   # initialize pygame
   pygame.joystick.init()
   pygame.display.init()
   if not pygame.joystick.get_count():
       print "\nPlease connect a joystick and run again.\n"
       quit()
   print "\n%d joystick(s) detected." % pygame.joystick.get_count()
   for i in range(pygame.joystick.get_count()):
       myjoy = pygame.joystick.Joystick(i)
       myjoy.init()
       joy.append(myjoy)
       print "Joystick %d: " % (i) + joy[i].get_name()
   print "Depress Button 8 to quit.\n"

   # run joystick listener loop
   joystickControl()

# allow use as a module or standalone script
if __name__ == "__main__":
   main()


and here is the servo.py that communicates with the serial port to Arduino.
Code: [Select]
#!/usr/bin/env python

################################################
# Module:   servo.py
# Created:  2 April 2008
# Author:   Brian D. Wendt
#   http://principialabs.com/
# Version:  0.2
# License:  GPLv3
#   http://www.fsf.org/licensing/
'''
Provides a serial connection abstraction layer
for use with Arduino "MultipleServos" sketch.
'''
################################################

import serial

usbport = 'COM7'
ser = serial.Serial(usbport, 9600)
#print ser

def move(servo, angle):
   '''Moves the specified servo to the supplied angle.

   Arguments:
       servo
         the servo number to command, an integer from 1-4
       angle
         the desired servo angle, an integer from 0 to 180

   (e.g.) >>> servo.move(2, 90)
          ... # "move servo #2 to 90 degrees"'''

   if (0 <= angle <= 180):
       ser.write(chr(255))
       ser.write(chr(servo))
       ser.write(chr(angle))
   else:
       print "Servo angle must be an integer between 0 and 180.\n"



amanmazleifg

***continued because of character limits.


and finally! the Arduino code!
Code: [Select]
/*
* ------------------------------
*   MultipleSerialServoControl
* ------------------------------
*
* Uses the Arduino Serial library
*  (http://arduino.cc/en/Reference/Serial)
* and the Arduino Servo library
*  (http://arduino.cc/en/Reference/Servo)
* to control multiple servos from a PC using a USB cable.
*
* Dependencies:
*   Arduino 0017 or higher
*     (http://www.arduino.cc/en/Main/Software)
*   Python servo.py module
*     (http://principialabs.com/arduino-python-4-axis-servo-control/)
*
* Created:  23 December 2009
* Author:   Brian D. Wendt
*   (http://principialabs.com/)
* Version:  1.0
* License:  GPLv3
*   (http://www.fsf.org/licensing/)
*
*/

// Import the Arduino Servo library
#include <Servo.h>

// Create a Servo object for each servo
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo12;
// TO ADD SERVOS:
//   Servo servo5;
//   etc...

// Common servo setup values
int minPulse = 600;   // minimum servo position, us (microseconds)
int maxPulse = 2370;// maximum servo position, us
int minPulse1 = 800;
int maxPulse1 = 3000;
// User input for servo and position
int userInput[3];    // raw input from serial buffer, 3 bytes
int startbyte;       // start byte, begin reading input
int servo;           // which servo to pulse?
int pos;             // servo angle 0-180
int i;               // iterator
int fpos1 = 90;
int fpos2 = 90;
int change = 5;

void setup()
{
 // Attach each Servo object to a digital pin
 servo1.attach(2, minPulse1, maxPulse1);//camera up and down
 servo2.attach(3, minPulse, maxPulse);
 servo3.attach(4, minPulse1, maxPulse1);//camera left and right
 servo4.attach(5, minPulse, maxPulse);
 servo12.attach(13, minPulse, maxPulse); //gun cocking servo
 // TO ADD SERVOS:
 //   servo5.attach(YOUR_PIN, minPulse, maxPulse);
 //   etc...

 // Open the serial connection, 9600 baud
 Serial.begin(9600);
}

void loop()
{
 // Wait for serial input (min 3 bytes in buffer)
 if (Serial.available() > 2) {
   // Read the first byte
   startbyte = Serial.read();
   // If it's really the startbyte (255) ...
   if (startbyte == 255) {
     // ... then get the next two bytes
     for (i=0;i<2;i++) {
       userInput[i] = Serial.read();
     }
     // First byte = servo to move?
     servo = userInput[0];
     // Second byte = which position?
     pos = userInput[1];
     // Packet error checking and recovery
     if (pos == 255) { servo = 255; }

     // Assign new position to appropriate servo
     switch (servo) {
     //----Axis Y----------------------
       case 1:
       if(userInput[1]==1)//if arduino detects 1 coming from python, goes into following loop
       {
         fpos1 = fpos1 + change;
       }
       if(userInput[1]==0)//if arduino detects 0 coming from python, goes into following loop
       {
         fpos1 = fpos1 - change;
       }
       fpos1 = constrain(fpos1, 50, 150); // limit value of angle
       servo1.write(fpos1);
       delay(10);
       break;
     //--------------------------------
       case 2:
         servo2.write(pos);
         break;
     //----Axis X----------------------  
       case 3:
       if(userInput[1]==3)//if arduino detects 3 coming from python, goes into following loop
       {
         fpos2 = fpos2 + change;
       }
       if(userInput[1]==4)//if arduino detects 4 coming from python, goes into following loop
       {
         fpos2 = fpos2 - change;
       }
       fpos2 = constrain(fpos2, 50, 150); // limit value of angle
       servo3.write(fpos2);
       delay(10);
       break;
     //-------------------------------
       case 4:
         servo4.write(pos);
         break;
       case 12:
         servo12.write(pos);
         break;
  // TO ADD SERVOS:
  //     case 5:
  //       servo5.write(pos);
  //       break;
  // etc...
     }
   }
 }

}


i really appreciate all the help i can get guys! sincerely!

Go Up