Mercurial > ukubik
changeset 63:9ffc6ec8fc64
Fix some bugs and add battery saving checks
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Wed, 27 Aug 2014 18:55:27 +0200 |
| parents | 46b0a837131e |
| children | 0c93a45e1477 |
| files | creep.py kubik.py leg.py robot.py servo.py servo/servo.ino |
| diffstat | 6 files changed, 72 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/creep.py Wed Aug 27 14:55:56 2014 +0200 +++ b/creep.py Wed Aug 27 18:55:27 2014 +0200 @@ -114,7 +114,7 @@ import serial import kubik - FPS = 32 + FPS = 50 robot = kubik.Robot(serial.Serial('/dev/rfcomm0', 115200)) creep = Creep(robot)
--- a/kubik.py Wed Aug 27 14:55:56 2014 +0200 +++ b/kubik.py Wed Aug 27 18:55:27 2014 +0200 @@ -21,7 +21,8 @@ class Robot(robot.Robot): accel_trim = [139, 136, 142] - battery_max = 230 + battery_max = 231 + battery_min = 190 def __init__(self, serial): self.legs = (
--- a/leg.py Wed Aug 27 14:55:56 2014 +0200 +++ b/leg.py Wed Aug 27 18:55:27 2014 +0200 @@ -90,7 +90,7 @@ ry = r * math.cos(a + radians) - self.base[1] self.move_to((rx, -ry * self.y_dir, None)) - def update(self, shift=(0, 0, 0)): + def update(self, shift=(0, 0, 0), send=True): """Send the positions to the servos.""" dx, dy, dz = shift x, y, z = self.position @@ -98,4 +98,5 @@ angles =self._inverse_kinematics(position) for joint, angle in zip(self, angles): joint.move_degrees(angle) - joint.update() + if send: + joint.update()
--- a/robot.py Wed Aug 27 14:55:56 2014 +0200 +++ b/robot.py Wed Aug 27 18:55:27 2014 +0200 @@ -10,6 +10,7 @@ legs = () accel_trim = [128.0, 128.0, 128.0] battery_max = 255 + battery_min = 0 def __init__(self): self.shift = [0.0, 0.0, 0.0] @@ -47,9 +48,13 @@ self._unshift(), ], 40) - def update(self): + def update(self, at_once=True): + servos = [] for leg in self.legs: - leg.update(self.shift) + leg.update(self.shift, send=not at_once) + servos.extend(leg) + if at_once: + self.legs[0].hip.update_all(servos) def get_accel(self): sensors = self.legs[0].hip.get_sensors() @@ -60,7 +65,8 @@ ] def get_battery(self): - return float(self.legs[0].hip.get_battery()) / self.battery_max + return float(self.legs[0].hip.get_battery() - + self.battery_min) / (self.battery_max - self.battery_min) def beep(self, frequency, duration): self.legs[0].hip.beep(frequency, duration)
--- a/servo.py Wed Aug 27 14:55:56 2014 +0200 +++ b/servo.py Wed Aug 27 18:55:27 2014 +0200 @@ -11,7 +11,8 @@ return angle def _word(value): - return chr(value & 0xff) + chr(value & 0xff00 >> 8) + value = int(value) + return chr(value & 0xff) + (chr((value & 0xff00) >> 8)) class Servo(object): span = 180 @@ -29,13 +30,16 @@ def update(self): angle = self.calculate_angle() command = '\xff%c%c' % (self.index, int(angle)) + freq = self.calculate_freq() + print (self.index, freq) + command = '\xfd%c%s' % (self.index, _word(freq)) self.serial.write(command) @classmethod def update_all(cls, servos): serial = servos[0].serial servos = sorted(servos, key=lambda servo: servo.index) - command = '\xfc%s' % ''.join(_word(servo.calculate_freq()) + command = '\xfe%s' % ''.join(chr(int(servo.calculate_angle())) for servo in servos) serial.write(command)
--- a/servo/servo.ino Wed Aug 27 14:55:56 2014 +0200 +++ b/servo/servo.ino Wed Aug 27 18:55:27 2014 +0200 @@ -3,7 +3,6 @@ */ #include <Servo.h> -#include <math.h> // Time of a signle frame, in milliseconds. #define FRAME_TIME 10 @@ -68,40 +67,19 @@ accel_buffer[accel_buffer_index][1] = analogRead(A1); accel_buffer[accel_buffer_index][2] = analogRead(A0); accel_buffer_index += 1; - if (accel_buffer_index > MAX_ACCEL_BUFFER) { + if (accel_buffer_index >= MAX_ACCEL_BUFFER) { accel_buffer_index = 0; } } + int _serial_read_word() { /* Read two bytes from the serial port and make an int from them. */ - return Serial.read() | Serial.read() << 8; -} - -double _norm(double a, double b) { - return sqrt(a * a + b * b); -} - -double _triangle(double a, double b, double c) { - return facos((a * a + b * b - c * c) / (2 * a * b)); -} - -int _radians_to_microseconds(double angle) { - while (angle < 0) { - angle += 2; - } - return SERVO_FREQ_MIN + (SERVO_FREQ_MAX - SERVO_FREQ_MIN) * angle; -} - -void move_leg(int leg, double x, double y, double z) { - double f = _norm(x, y) - LEG_COXA; - double d = _norm(f, z); - double hip = fatan2(y, x) + 0.25 * legs[leg][4]; - double knee = fatan2(-z, f) - _triangle(LEG_FEMUR, d, LEG_TIBIA); - double ankle = _triangle(LEG_FEMUR, LEG_TIBIA, d) - 0.5; - servos[legs[leg][0]].writeMicroseconds(_radians_to_microseconds(hip)); - servos[legs[leg][1]].writeMicroseconds(_radians_to_microseconds(knee)); - servos[legs[leg][2]].writeMicroseconds(_radians_to_microseconds(ankle)); + int low; + int high; + low = Serial.read(); + high = Serial.read(); + return low | (high << 8); } void do_servo_degrees() { @@ -143,17 +121,6 @@ } } -void do_move_leg() { - /* Move the leg to a position in space. */ - int leg = Serial.read(); - int x = Serial.read() - 128; - int y = Serial.read() - 128; - int z = Serial.read() - 128; - if (leg >= 0 && leg <= 4) { - move_leg(leg, x, y, z); - } -} - void do_accel() { /* Report the readings of the acceleration sensor. */ int avg_x = 0; @@ -232,13 +199,6 @@ if (Serial.available() < MAX_SERVO * 2) { return; } do_servos_microseconds(); break; - case 0xfb: - /* Move a leg to a position in space. */ - if (Serial.available() < 4) { - return; - } - do_move_leg(); - break; case 0xf0: /* Read the accelerometer sensor. */ do_accel(); @@ -256,21 +216,55 @@ serial_command = 0; } -void setup() { - int servo; - - Serial.begin(SERIAL_SPEED); - pinMode(A3, OUTPUT); - tone(A3, 440, 100); - delay(20); - tone(A3, 220, 150); - for (servo = 0; servo < MAX_SERVO; servo += 1) { +void unfold() { + for (int servo = MAX_SERVO - 1; servo >= 0; servo -= 1) { /* First 2 pins are used for the serial. */ servos[servo].attach(servo + 2, SERVO_FREQ_MIN, SERVO_FREQ_MAX); servos[servo].writeMicroseconds(1500); /* Don't set all servos at once, save power. */ delay(150); } + delay(50); + tone(A3, 440, 200); + delay(200); + tone(A3, 523, 100); + delay(150); + tone(A3, 880, 100); +} + +void fold() { + /* Folds the robots and shut downs all servos. Doesn't return. */ + for (int leg = 0; leg < 4; leg += 1) { + int d = legs[leg][3] * legs[leg][4]; + servos[legs[leg][0]].write(90 + 45 * d); + servos[legs[leg][1]].write(90 - 90 * d); + servos[legs[leg][2]].write(90 + 90 * d); + } + delay(250); + for (int servo = 0; servo < MAX_SERVO; servo += 1) { + servos[servo].detach(); + } + while (1) { + delay(1000); + } +} + +void check_battery() { + int reading = analogRead(A7); + if (reading < 762) { + /* At about 3.74V start an alarm. */ + tone(A3, 880, 100); + } + if (reading < 758 + 500) { + /* At about 3.72V shut down. */ + fold(); + } +} + +void setup() { + Serial.begin(SERIAL_SPEED); + pinMode(A3, OUTPUT); + unfold(); } void loop() { @@ -279,6 +273,7 @@ do_serial_command(); if (now > last_tick + FRAME_TIME || now < last_tick) { read_accel(); + check_battery(); last_tick = now; } }
