Terminé con una configuración de motor diferente. Mi motor parte delantera apunta hacia abajo y vuelve un poco equipo de barrio que entonces da vuelta a las ruedas delanteras. Esto significó que ninguno del código de Randy era aplicable a mi proyecto.
Me puse a buscar en el mundo algo repulsivo de programación de Arduino. Es todas las variables globales y proyectos de archivo. Me resultó difícil comprender muchos de los ejemplos disponibles en línea, no porque eran conceptos particularmente difíciles, sino porque eran tantos pobres ejemplos de programación que detecta mi refinado no podrían hacer sentido.
También el entorno de programación Arduino deja mucho que desear. Me llevan a el proyecto de embedXcode excelente, que me permitió utilizar XCode en lugar.
Una vez tuve un ambiente agradable me puse a buscar las mejores formas de escribir código para el Arduino. Resulta que todo es a C++, que sé mucho sobre. La clase MotorControl que escribí, que hace uso de una clase de DasPing, está más abajo.
Limpiar el código como esta habilitada mi final sketch de Arduino para parecerse a la siguiente:
#include "Arduino.h" #include "DasPing.h" #include "MotorControl.h" MotorControl *mc; void setup() { Serial.begin(9600); mc = new MotorControl(7, 100, 125); mc->setUp(); } void loop() { mc->checkDistance(); if (mc->distance > 12 || mc->distance == 0) { mc->straighten(); mc->forward(mc->getBaseSpeed()); } else { mc->right(); mc->backward(); } }
Se puede ver el comportamiento real del robot hay. Abstrayendo las clases MotorControl y DasPing, para controlar el movimiento y sentido de distancia respectivamente, me permitió trabajar con el mucho más divertido problema de llevar un robot a la vida.
El comportamiento básico que se muestra en este video se deriva de aproximadamente 10 líneas de código, una vez que resumen todo lo que usted no necesita preocuparse.
Aquí están las definiciones de clase MotorControl y DasPing, seguidas por los archivos de ejecución.
MotorControl.h
// // MotorControl.h // // // Created by David Worley on 1/1/13. // // #ifndef ____MotorControl__ #define ____MotorControl__ #include "Arduino.h" #include "DasPing.h" class MotorControl { public: MotorControl(int pingPin, int defaultDelay, int baseSpeed); void setUp(); int distance; int getBaseSpeed(); void setBaseSpeed(int baseSpeed); void forward(int goSpeed); void backward(); void left(); void right(); void stop(); void checkDistance(); void easeToBaseSpeed(); void slowFromBaseSpeed(); void straighten(); protected: int _baseSpeed; int _turnSpeed; // for controlling the turn motor int _distance; int _defaultDelay; DasPing *_pinger; // motor 1, turning int _brake1; int _direction1; int _speed1; // motor 2, forward & reverse int _brake2; int _direction2; int _speed2; }; #endif /* defined(____MotorControl__) */
MotorControl.cpp
// // MotorControl.cpp // // A class for controlling a particular motor configuration // using the Arduino motor shield and a Parallax Ping sensor. // // Created by David Worley on 1/1/13. // // #include "MotorControl.h" MotorControl::MotorControl(int pingPin, int defaultDelay, int baseSpeed) { Serial.println("MotorControl init."); _pinger = new DasPing(pingPin); this->checkDistance(); _defaultDelay = defaultDelay; this->setBaseSpeed(baseSpeed); // since we're using a specific configuration, we know // what values to use based on the motor shield documentation _brake1 = 9; _direction1 = 12; _speed1 = 3; _brake2 = 8; _direction2 = 13; _speed2 = 11; _turnSpeed = 255; // set to max for the turn motor } void MotorControl::setUp() { Serial.println("MotorControl setUp."); // establish motor direction pins pinMode(_direction1, OUTPUT); pinMode(_direction2, OUTPUT); // brakes pinMode(_brake1, OUTPUT); pinMode(_brake2, OUTPUT); digitalWrite(_brake1, HIGH); digitalWrite(_brake2, HIGH); } void MotorControl::forward(int goSpeed) { digitalWrite(_brake2, LOW); digitalWrite(_direction2, LOW); analogWrite(_speed2, goSpeed); delay(_defaultDelay); } void MotorControl::backward() { digitalWrite(_brake2, LOW); digitalWrite(_direction2, HIGH); analogWrite(_speed2, 155); // back up at high speed delay(_defaultDelay); } void MotorControl::left() { digitalWrite(_brake2, LOW); digitalWrite(_direction2, HIGH); analogWrite(_speed2, _turnSpeed); delay(_defaultDelay); } void MotorControl::right() { digitalWrite(_brake1, LOW); digitalWrite(_direction1, LOW); analogWrite(_speed1, _turnSpeed); } void MotorControl::stop() { digitalWrite(_brake1, HIGH); digitalWrite(_brake2, HIGH); analogWrite(_speed1, 0); analogWrite(_speed2, 0); delay(_defaultDelay); } void MotorControl::straighten() { digitalWrite(_brake1, HIGH); analogWrite(_speed1, 0); } void MotorControl::checkDistance() { _pinger->pingDistance(); _distance = _pinger->distance(); distance = _distance; } int MotorControl::getBaseSpeed() { return _baseSpeed; } void MotorControl::setBaseSpeed(int baseSpeed) { _baseSpeed = baseSpeed; } void MotorControl::easeToBaseSpeed() { for (int i = 0; i <= _baseSpeed; i++) { forward(i); delay(100); // every 1/10th of a second, speed up } } void MotorControl::slowFromBaseSpeed() { for (int i = _baseSpeed; i >= 0; i = i - 10) { forward(i); delay(50); } this->stop(); }
DasPing.h
// // DasPing.h // // // Created by David Worley on 1/2/13. // // #ifndef ____DasPing__ #define ____DasPing__ #include "Arduino.h" class DasPing { public: DasPing(int pingPin); void pingDistance(); int distance(); protected: int _distance; int _pin; int microsecondsToInches(long microseconds); }; #endif /* defined(____DasPing__) */
DasPing.cpp
// // DasPing.cpp // // A class for controlling the Parallax Ping sensor // // Created by David Worley on 1/2/13. // // #include "DasPing.h" DasPing::DasPing(int pingPin) { _distance = 0; _pin = pingPin; } void DasPing::pingDistance() { int duration; // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); delayMicroseconds(2); digitalWrite(_pin, HIGH); delayMicroseconds(5); digitalWrite(_pin, LOW); // The same pin is used to read the signal from the PING))): a HIGH // pulse whose duration is the time (in microseconds) from the sending // of the ping to the reception of its echo off of an object. pinMode(_pin, INPUT); duration = pulseIn(_pin, HIGH); // convert the time into a distance _distance = this->microsecondsToInches(duration); } int DasPing::distance() { return _distance; } int DasPing::microsecondsToInches(long microseconds) { // According to Parallax's datasheet for the PING))), there are // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per // second). This gives the distance travelled by the ping, outbound // and return, so we divide by 2 to get the distance of the obstacle. // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf return microseconds/74/2; }