Playing with Dagu Rover and gripper from Bajdi on Vimeo.
Finally got around to make a sketch to remote control my Rover 5 and gripper. I started with a sketch to control just the gripper with a 2 axis joystick and 2 buttons to open and close the gripper. While testing that sketch I made a little mistake that stripped the gears of the claw servo. Luckily I received a new servo very fast and while I was at it I ordered a spare one 🙂 Most servos can move 180 degrees and if you have mounted a servo so it can only move less then 180 degrees because of mechanical reasons it’s best to limit the movement of the servo in software. I hadn’t thought of that and my code sent the servo to a position it physically couldn’t go to and that stripped the metal gears of the servo. Luckily these little Chinese servos are pretty cheap so it wasn’t a big loss. It’s a lesson learnt.
I did have some more problems testing the gripper. When I use the sketch with only the code to control the gripper the servos move very fast and I had to slow them down in the sketch else I couldn’t control them accurately. When I added that sketch to my existing remote control sketch of my rover the servos where very slow so I had to change it so they moved faster. To power the 3 servos I use a very cheap 4A UBEC (5V regulator). I soldered a bunch of pins to a small PCB to connect the UBEC to the servos and the micro controller. I’ve even added a big capacitor to the board to help keep the noise of the UBEC under control. I was a bit worried that it will interfere with my 2,4GHz wireless nRF24L01 module. Since I’ve added the gripper my Lipo batteries seem to go flat a lot faster, those 3 servos must draw a considerate amount of power.
I used my self made remote control (Arduino Uno + joystick shield + nRF24L01 + I2C 4×20 LCD) to control the Rover and gripper. The LCD shows the current of the 4 motors and the battery voltages of the battery in the remote and the rover.
Here are the sketches I’ve used in the video:
The sketch that went in my self made remote control:
// http://www.bajdi.com // Sketch to remote control Dagu Rover 5 with 3 DIF gripper // Nrf24L01 connected to Arduino Uno // Nrf24L01 connection details http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo // 4 x 20 I2C LCD // Transmit analog values from joystick and the state of 3 buttons to the Rover 5 using RF24 library. // Receive 4 floats (current values from the motors) and the battery voltage from the Rover 5 and display it on the LCD #include <SPI.h> #include <nRF24L01.h> #include "RF24.h" #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <Bounce.h> LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 RF24 radio(8,9); const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; int joystick[5]; float rover[5]; float batr; const int z = 2; const int clawopen = 3; const int clawclose = 6; int roverState; // the rover state of the output pin Bounce bouncerz = Bounce( z, 10 ); long previousMillis = 0; const int interval = 25; void setup(){ Serial.begin(9600); pinMode(z, INPUT); digitalWrite(z, HIGH); pinMode(clawopen , INPUT); pinMode(clawclose , INPUT); digitalWrite(clawopen, HIGH); digitalWrite(clawclose, HIGH); radio.begin(); radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); radio.startListening(); lcd.init(); // initialize the lcd lcd.backlight(); lcd.setCursor(0,0); lcd.print("M1="); lcd.setCursor(8,0); lcd.print("M2="); lcd.setCursor(0,1); lcd.print("M3="); lcd.setCursor(8,1); lcd.print("M4="); lcd.setCursor(0,2); lcd.print("Bat remote = "); lcd.setCursor(0,3); lcd.print("Bat rover = "); } void loop(){ joystick[0] = analogRead(A0); joystick[1] = analogRead(A1); joystick[2] = roverState; batr = analogRead(A3) / 102.3; if ( bouncerz.update() ) { if ( bouncerz.read() == LOW) { if ( roverState == HIGH ) { roverState = LOW; } else { roverState = HIGH; } } } joystick[3] = digitalRead(clawopen); joystick[4] = digitalRead(clawclose); if ( radio.available() ) { unsigned long roverMillis = millis(); if(roverMillis - previousMillis > interval) { previousMillis = roverMillis; // Dump the payloads until we've gotten everything bool done = false; while (!done) { // Fetch the payload, and see if this was the last one. done = radio.read( &rover, sizeof(rover) ); } } radio.stopListening(); bool ok = radio.write( &joystick, sizeof(joystick) ); radio.startListening(); } lcd.setCursor(3,0); lcd.print(rover[0]); lcd.setCursor(11,0); lcd.print(rover[1]); lcd.setCursor(3,1); lcd.print(rover[2]); lcd.setCursor(11,1); lcd.print(rover[3]); lcd.setCursor(13,2); lcd.print(batr); lcd.setCursor(12,3); lcd.print(rover[4]); }
The sketch that went into the Mega1280 based micro controller on the Rover 5:
// http://www.bajdi.com // Dagu Rover 5 chassis with 4 motors and 3 DOF gripper // Remote control through Nrf24L01 2,4GHz wireless module // µcontroller = Dagu Red back spider, Arduino Mega 1280 compatible // Motor controller = Dagu 4 channel motor controller #include <SPI.h> #include <nRF24L01.h> #include "RF24.h" #include "Ultrasonic.h" #include <Servo.h> Servo bottomservo; // create servo object to control a servo Servo shouldservo; // create servo object to control a servo Servo clawservo; // create servo object to control a servo /* Nrf24L01 pinout 1 GND 2 VCC (3,3V) 3 CE pin 48 on Mega 1280 4 CSN pin 49 on Mega 1280 5 SCK pin 52 on Mega 1280 6 MOSI pin 51 on Mega 1280 7 MISO pin 50 on Mega 1280 8 IRQ (not used) */ RF24 radio(48,49); const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; const int DirM1 = 30; // direction motor 1 const int DirM2 = 31; // direction motor 2 const int DirM3 = 32; // direction motor 3 const int DirM4 = 33; // direction motor 4 const int PWMM1 = 4; // pwm motor 1 const int PWMM2 = 5; // pwm motor 2 const int PWMM3 = 6; // pwm motor 3 const int PWMM4 = 7; // pwm motor 4 uint8_t fs; // forward speed uint8_t bs; // backward speed uint8_t ls; // turn left speed uint8_t rs; // turn right speed int bat; // analog reading of battery voltage through voltage divider const int lowbat = 34; // low battery led (red) const int buzzer = 35; // buzzer const int orange = 38; // orange leds const int headlight = 39; // white leds const int TRIG = 36; const int ECHO = 37; uint8_t XNewPos = 110; uint8_t YNewPos = 146; uint8_t ZNewPos = 100; int Xcounter = 0; int Ycounter = 0; int Zcounter = 0; int XOldPos; int YOldPos; int ZOldPos; long previousMillis1 = 0; long previousMillis2 = 0; long previousMillis3 = 0; const int intervalg = 50; Ultrasonic SRF6A(TRIG, ECHO); int joystick[5]; // Array with 2 analog values (X,Y-axis) and one digital (Z-axis) from transmitter/joystick float rover[5]; // Array with the 4 motor rover values, to sent to remote control int apin[] = { A1, A2, A3, A4 }; // analog pin array long previousMillis = 0; const int interval = 100; void setup() { pinMode(DirM1, OUTPUT); // direction motor 1, left front pinMode(DirM2, OUTPUT); // direction motor 2, left rear pinMode(DirM3, OUTPUT); // direction motor 3, right front pinMode(DirM4, OUTPUT); // direction motor 4, right rear pinMode(PWMM1, OUTPUT); // PWM motor 1 pinMode(PWMM2, OUTPUT); // PWM motor 2 pinMode(PWMM3, OUTPUT); // PWM motor 3 pinMode(PWMM4, OUTPUT); // PWM motor 4 pinMode(lowbat, OUTPUT); // low battery led (red) pinMode(buzzer, OUTPUT); // buzzer pinMode(orange, OUTPUT); // orange leds pinMode(headlight, OUTPUT); // white leds radio.begin(); radio.openWritingPipe(pipes[1]); radio.openReadingPipe(1,pipes[0]); radio.startListening(); bottomservo.attach(9); // attaches the servo on pin 9 to the servo object shouldservo.attach(10); // attaches the servo on pin 10 to the servo object clawservo.attach(11); // attaches the servo on pin 11 to the servo object } void loop() { rover[4] = analogRead(A0) /102.3; if ( radio.available() ) { // Dump the payloads until we've gotten everything bool done = false; while (!done) { // Fetch the payload, and see if this was the last one. done = radio.read( &joystick, sizeof(joystick) ); } if (rover[4] > 7.4) { if(joystick[2] == LOW) // 760 / 1023 * 5 * 2 = 7,4V from battery { digitalWrite(headlight, HIGH); // turn on headlights if(SRF6A.Ranging(CM) < 5){ digitalWrite(buzzer, HIGH); // we're going to crash } else { digitalWrite(buzzer, LOW); } if (joystick[0] > 490 && joystick[0] < 510 && joystick[1] > 490 && joystick[1] < 510 ) // joystick is centered { stopped(); } if (joystick[1] >= 505 && joystick[0] > 490 && joystick[0] < 510) // joystick forward = all motors forward { bs = (map(joystick[1], 510, 1023, 30, 250)); backward(bs); } if (joystick[1] <= 490 && joystick[0] > 490 && joystick[0] < 510) // joystick backward = all motors backward { fs = (map(joystick[1], 490, 0, 30, 250)); forward(fs); } if (joystick[0] <= 490 && joystick[1] > 490 && joystick[1] < 510) // joystick left = left motors backward && right motors forward { rs = (map(joystick[0], 490, 0, 30, 250)); turnright(rs); } if (joystick[0] >= 510 && joystick[1] > 490 && joystick[1] < 510) // joystick right = left motors forward && right motors backward { ls = (map(joystick[0], 510, 1023, 30, 250)); turnleft(ls); } } else { stopped(); digitalWrite(headlight, LOW); // turn off headlights digitalWrite(orange, HIGH); if ( joystick[3] == LOW && ZNewPos < 169) { Zcounter+=2; ZNewPos = ZNewPos + Zcounter; } if ( joystick[4] == LOW && ZNewPos > 92) { Zcounter+=2; ZNewPos = ZNewPos - Zcounter; } if (joystick[0] > 600 && XNewPos < 180) { Xcounter+=3; XNewPos = XNewPos + (Xcounter); } if (joystick[0] < 400 && XNewPos > 30) { Xcounter+=3; XNewPos = XNewPos - (Xcounter); } if (joystick[1] < 400 && YNewPos < 174) { Ycounter+=3; YNewPos = YNewPos + (Ycounter); } if (joystick[1] > 600 && YNewPos > 50) { Ycounter+=3; YNewPos = YNewPos - (Ycounter); } unsigned long currentMillis1 = millis(); if(XOldPos != XNewPos && currentMillis1 - previousMillis1 > intervalg) { previousMillis1 = currentMillis1; Xcounter = 0; XOldPos = XNewPos; if(XNewPos < 30) { XNewPos = 30; } if(XNewPos > 180) { XNewPos = 180; } bottomservo.write(XNewPos); // tell servo to go to position in variable 'XNewPos' } unsigned long currentMillis2 = millis(); if(YOldPos != YNewPos && currentMillis2 - previousMillis2 > intervalg) { previousMillis2 = currentMillis2; Ycounter = 0; YOldPos = YNewPos; if(YNewPos < 50) { YNewPos = 50; } if(YNewPos > 174) { YNewPos = 174; } shouldservo.write(YNewPos); // tell servo to go to position in variable 'YNewPos' } unsigned long currentMillis3 = millis(); if(ZOldPos != ZNewPos && currentMillis3 - previousMillis3 > intervalg) { // Issue command only if desired position changes previousMillis3 = currentMillis3; Zcounter = 0; ZOldPos = ZNewPos; // Set servo in degrees from approximately 0 to 180 if(ZNewPos < 92) { ZNewPos = 92; } if(ZNewPos > 169) { ZNewPos = 169; } clawservo.write(ZNewPos); // tell servo to go to position in variable 'ZNewPos' } } } } unsigned long roverMillis = millis(); if(roverMillis - previousMillis > interval) { previousMillis = roverMillis; radio.stopListening(); bool ok = radio.write( &rover, sizeof(rover) ); radio.startListening(); } // 4 analog readings from motor controller = motor rover for (int i=0; i<4; i++) { rover[i] = analogRead( apin[i] )/ 1023.0 * 5.0; } } void stopped() { analogWrite(PWMM1, 0); analogWrite(PWMM2, 0); analogWrite(PWMM3, 0); analogWrite(PWMM4, 0); digitalWrite(orange, LOW); } void forward(int fs) { digitalWrite(DirM1, HIGH); digitalWrite(DirM2, HIGH); digitalWrite(DirM3, HIGH); digitalWrite(DirM4, HIGH); analogWrite(PWMM1, fs); analogWrite(PWMM2, fs); analogWrite(PWMM3, fs); analogWrite(PWMM4, fs); digitalWrite(orange, LOW); } void backward(int bs) { digitalWrite(DirM1, LOW); digitalWrite(DirM2, LOW); digitalWrite(DirM3, LOW); digitalWrite(DirM4, LOW); analogWrite(PWMM1, bs); analogWrite(PWMM2, bs); analogWrite(PWMM3, bs); analogWrite(PWMM4, bs); digitalWrite(orange, LOW); } void turnleft(int ls) { digitalWrite(DirM1, LOW); digitalWrite(DirM2, LOW); digitalWrite(DirM3, HIGH); digitalWrite(DirM4, HIGH); analogWrite(PWMM1, ls); analogWrite(PWMM2, ls); analogWrite(PWMM3, ls); analogWrite(PWMM4, ls); digitalWrite(orange, HIGH); } void turnright(int rs) { digitalWrite(DirM1, HIGH); digitalWrite(DirM2, HIGH); digitalWrite(DirM3, LOW); digitalWrite(DirM4, LOW); analogWrite(PWMM1, rs); analogWrite(PWMM2, rs); analogWrite(PWMM3, rs); analogWrite(PWMM4, rs); digitalWrite(orange, HIGH); }
this is pretty cool!
where or what type of servo did you use? I have the DAGU claw where the servo mounts on the bottom center(not to the side) but I can’t find any servo compatible with the spacing.
The slot to hold the servo is 29.79mm with single mounting holes.
thanks,