Go Down

Topic: arduino robot: ps2 mouse + pololu motor controller (Read 1 time) previous topic - next topic

Mr_Bene_Fit

Oct 14, 2009, 02:19 pm Last Edit: Oct 14, 2009, 02:19 pm by Mr_Bene_Fit Reason: 1
hello all,

we trying to build an arduino robot ...
by using the following components:

1x Pololu Dual MC33887 motor controller
2x GHM-16 gearhead motors
2x QME-01 encoders (attached to the motors)
1x ps2 mouse
1x Arduino Duemilanove

specs
http://www.looksgood.de/_tmp/ghm16.pdf
http://www.looksgood.de/_tmp/encodeur-quadrature-qme-01-lynxmotion-assembly-guide.pdf
http://www.looksgood.de/_tmp/schaltplan2009.10.14.pdf

actually we are quite happy that we reached already the step, that we have everything up and running:
we get precise encoder values, we are able to control the motors with PWM via the pololu controller and with the help of the ps2 library the mouse is also working as an input sensor.

but so far we couldn't solve one strange problem:
if we drive the motors above certain PWM values the whole arduino freezes :(
for instances:
Code: [Select]

// causes freeze
out_motorPWM[0] = 255;
out_motorPWM[1] = 255;

Code: [Select]

// working
out_motorPWM[0] = 127;
out_motorPWM[1] = 127;

please note also, without reading the mouse values in the main loop, we have no problems to drive the motors with any PWM value without any freeze.
so it seems to us that we have some strange interaction with the motors and the ps2 mouse lib.

any hint is very welcome. see below code and wiring.

thanks
benedikt




Code: [Select]

#include <ps2.h>
// Ps2mouse lib -> http://www.arduino.cc/playground/ComponentLib/Ps2mouse

// ---- pins ----
#define pinM1_DirectionA 4
#define pinM1_DirectionB 5
#define pinM1_PWM 10

#define pinM2_DirectionA 13
#define pinM2_DirectionB 7
#define pinM2_PWM 11

#define pinE1_A 2
#define pinE1_B 8

#define pinE2_A 3
#define pinE2_B 6

#define pinP_data 9
#define pinP_clock 12

PS2 mouse(pinP_clock, pinP_data);

//  ---- vars ----
int out_motorPWM[2] = {
 0,0};

// encoder 1
volatile int in_steps1 = 0;
int in_E1_prev = LOW;
int in_E1_curr = LOW;

// encoder 2
volatile int in_steps2 = 0;
int in_E2_prev = LOW;
int in_E2_curr = LOW;

// mouse
char mstat = '0';
char mx = '0';
char my = '0';


void setup() {
 // motor controller
 pinMode(pinM1_DirectionA, OUTPUT);
 pinMode(pinM1_DirectionB, OUTPUT);
 pinMode(pinM1_PWM, OUTPUT);

 pinMode(pinM2_DirectionA, OUTPUT);
 pinMode(pinM2_DirectionB, OUTPUT);
 pinMode(pinM2_PWM, OUTPUT);

 // encoders
 pinMode (pinE1_A,INPUT);
 pinMode (pinE1_B,INPUT);
 pinMode (pinE2_A,INPUT);
 pinMode (pinE2_B,INPUT);
 attachInterrupt(0, doEncoder1, CHANGE);
 attachInterrupt(1, doEncoder2, CHANGE);

 Serial.begin(19200);
 Serial.println("hello");

 mouse_init();
 // wait for the mouse to be ready
 delay(2000);
}

void loop() {
 // ---- read data from computer host ----
 if (Serial.available() > 0) {
   int incomingByte = Serial.read();
   // turn on both motors
   if (incomingByte == 'h') {
     // cause arduino to freeze
     out_motorPWM[0] = 255;
     out_motorPWM[1] = 255;
     // works
     //out_motorPWM[0] = 127;
     //out_motorPWM[1] = 127;
   }
   // turn off both motors
   if (incomingByte == 'l') {
     out_motorPWM[0] = 0;
     out_motorPWM[1] = 0;
   }
 }
 
 // ---- set PWM + direction motor controller ----
 drive("motor1");
 drive("motor2");

 analogWrite(pinM1_PWM, abs(out_motorPWM[0]));
 analogWrite(pinM2_PWM, abs(out_motorPWM[1]));  
 

 // ---- read mouse data ----
 mouse.write(0xeb);  // give me data!
 mouse.read();      // ignore ack
 mstat = mouse.read();
 mx = mouse.read();
 my = mouse.read();


 // ---- send data to host ----
 Serial.print(in_steps1);
 Serial.print(';');
 Serial.print(in_steps2);
 Serial.print(';');
 Serial.print(mx, DEC);
 Serial.print(';');
 Serial.print(my, DEC);
 Serial.println();

 // reset variables after sending data, we just wanna have the delta
 in_steps1 = 0;
 in_steps2 = 0;

}


// ---- turn motros on + set direction ----
void drive(char m[]) {
 if (m=="motor1" && out_motorPWM[0]>=0) { // forward
   digitalWrite(pinM1_DirectionA, HIGH);
   digitalWrite(pinM1_DirectionB, LOW);
 }
 else if (m=="motor1" && out_motorPWM[0]<0) { // backward
   digitalWrite(pinM1_DirectionA, LOW);
   digitalWrite(pinM1_DirectionB, HIGH);
 }
 else if (m=="motor2" && out_motorPWM[1]>=0) { // forward
   digitalWrite(pinM2_DirectionA, HIGH);
   digitalWrite(pinM2_DirectionB, LOW);
 }
 else if (m=="motor2" && out_motorPWM[1]<0) { // backward
   digitalWrite(pinM2_DirectionA, LOW);
   digitalWrite(pinM2_DirectionB, HIGH);
 }
}


// ---- encoder interrupts event ----
void doEncoder1() {
 // left motor, cw = forward
 if ((digitalRead(pinE1_A) == HIGH)) {
   if (digitalRead(pinE1_B) == LOW) {
     in_steps1++;
   }
   else {
     in_steps1--;
   }
 }
 else {
   if (digitalRead(pinE1_B) == LOW) {
     in_steps1--;
   }
   else {
     in_steps1++;
   }
 }
}

void doEncoder2() {
 // right motor, cw = backward
 if (digitalRead(pinE2_A) == HIGH) {
   if (digitalRead(pinE2_B) == LOW) {
     in_steps2--;
   }
   else {
     in_steps2++;
   }
 }
 else {
   if (digitalRead(pinE2_B) == LOW) {
     in_steps2++;
   }
   else {
     in_steps2--;
   }
 }
}

// ---- mouse ----
void mouse_init()
{
 mouse.write(0xff);  // reset
 mouse.read();  // ack byte
 mouse.read();  // blank */
 mouse.read();  // blank */
 mouse.write(0xf0);  // remote mode
 mouse.read();  // ack
 delayMicroseconds(100);
}

Mike Rice

What is the rating of your power supply, and what do the motors draw?
It's possible that the motor load at full power is exceeding the supply rating.

Another thing I would check is brush noise (assuming these are the typical less expensive DC motors). Brush noise can cause all sorts of headaches.

A NPO cap across the motor terminals helps squelch the noise (and also extends the life of the brushes). Keep the leads as short as possible.

Choke inductors in series with the motor leads also help a lot.

Its possible there is some 'unintended behavior' (bug) in the PS2 library, but given that it 'almost' works, I would check these things before delving into the library code.

Mr_Bene_Fit

hello mike,

our motor controller can handle 3A but both motors have together only something like 2A. we have also a capacitor attached, see picture. plus we drove yesterday evening the robot without problems in "remote car" style for hours (of course without the ps2 mouse).

what do you think? a bug in the ps2 lib?

thanks benedikt


Pepe34

PS2 mouse lib has no build-in timeouts. It waits for high / low values on clock / data pins in infinite while loops. If (maybe due to some noise from motors) clock or data pins stay in unexpected level, the code waits in loop.

mem

I added a method to my version of the ps2 library that tests to see if a mouse is connected. Perhaps somehthing like this could help here

Code: [Select]
boolean PS2::IsResponding()
{
 /* put pins in output mode */
 gohi(_ps2data);
 gohi(_ps2clk);
 delayMicroseconds(300);
 golo(_ps2clk);
 delayMicroseconds(300);
 golo(_ps2data);
 delayMicroseconds(10);
 gohi(_ps2clk);
 for(uint8_t i = 0; i < 200; i++) {
   if(digitalRead(_ps2clk) == LOW){    /* wait for mouse to take control of clock); */
     gohi(_ps2clk);
     delay(50);  // wait for mouse to timeout
     return true;    
   }
   delay(1);
 }
 return false;  // mouse did not grab clock
}


The isResponding method returns true of a mouse responds to the command. It returns false if no response after a short timeout

Go Up