Diferencia entre revisiones de «Robot sigue líneas con Arduino»
Línea 66: | Línea 66: | ||
Para que funcione, necesitamos la biblioteca correspondiente. En los últimos Arduino IDE es tan simple como ir al gestor de Bibliotecas y importar la QTRSensors. | Para que funcione, necesitamos la biblioteca correspondiente. En los últimos Arduino IDE es tan simple como ir al gestor de Bibliotecas y importar la QTRSensors. | ||
La biblioteca funciona tanto para el QTR-8RC como el QTR-8A, pero | La biblioteca funciona tanto para el QTR-8RC como el QTR-8A, pero cambia la manera de configurarlo: | ||
<syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | <syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | ||
// Crear un objeto para | // Crear un objeto para 8 sensores en los pines digitales 2,4,5,6,7,10 y en los analogicos A4 A5 | ||
QTRSensors qtr; | |||
qtr.setTypeRC(); | |||
qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, 8); | |||
qtr.setEmitterPin(16); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Línea 85: | Línea 79: | ||
Calibrar los sensores es lo primero que debería hacer el robot. Así, en la rutina de inicialización (setup), se recomienda lanzar este código: | Calibrar los sensores es lo primero que debería hacer el robot. Así, en la rutina de inicialización (setup), se recomienda lanzar este código: | ||
<syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | <syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | ||
void setup() | void setup() | ||
{ | { | ||
pinMode(A3, OUTPUT); // LED para indicar que está calibrando | |||
// | |||
// configure the sensors | |||
qtr.setTypeRC(); | qtr.setTypeRC(); | ||
qtr.setSensorPins((const uint8_t[]){ | qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, SensorCount); | ||
qtr.setEmitterPin(16); | |||
// | |||
// | delay(500); | ||
// | //pinMode(A3, OUTPUT); | ||
// | digitalWrite(A3, HIGH); // turn on Arduino's LED to indicate we are in calibration mode | ||
// | |||
// 2.5 ms RC read timeout (default) * 10 reads per calibrate() call | |||
for ( | // = ~25 ms per calibrate() call. | ||
// Call calibrate() 400 times to make calibration take about 10 seconds. | |||
for (uint16_t i = 0; i < 400; i++) | |||
{ | { | ||
qtr.calibrate(); | qtr.calibrate(); | ||
} | } | ||
// | digitalWrite(A3, LOW); // turn off Arduino's LED to indicate we are through with calibration | ||
// | |||
// print the calibration minimum values measured when emitters were on | |||
Serial.begin(9600); | |||
for (uint8_t i = 0; i < SensorCount; i++) | |||
{ | |||
Serial.print(qtr.calibrationOn.minimum[i]); | |||
Serial.print(' '); | |||
} | |||
Serial.println(); | |||
// print the calibration maximum values measured when emitters were on | |||
for (uint8_t i = 0; i < SensorCount; i++) | |||
{ | |||
Serial.print(qtr.calibrationOn.maximum[i]); | |||
Serial.print(' '); | |||
} | |||
Serial.println(); | |||
Serial.println(); | |||
delay(1000); | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Línea 118: | Línea 129: | ||
<syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | <syntaxhighlight lang="c" style="font-family:monospace; font-size:0.8em;"> | ||
#include <QTRSensors.h> | #include <QTRSensors.h> | ||
// This example is designed for use with eight RC QTR sensors. These | |||
// reflectance sensors should be connected to digital pins 3 to 10. The | |||
// sensors' emitter control pin (CTRL or LEDON) can optionally be connected to | |||
// | // digital pin 2, or you can leave it disconnected and remove the call to | ||
// | // setEmitterPin(). | ||
// | // | ||
// The setup phase of this example calibrates the sensors for ten seconds and | |||
// turns on the Arduino's LED (usually on pin 13) while calibration is going | |||
// on. During this phase, you should expose each reflectance sensor to the | |||
// lightest and darkest readings they will encounter. For example, if you are | |||
// making a line follower, you should slide the sensors across the line during | |||
// the calibration phase so that each sensor can get a reading of how dark the | |||
// line is and how light the ground is. Improper calibration will result in | |||
// poor readings. | |||
// | |||
// The main loop of the example reads the calibrated sensor values and uses | |||
// them to estimate the position of a line. You can test this by taping a piece | |||
// of 3/4" black electrical tape to a piece of white paper and sliding the | |||
// sensor across it. It prints the sensor values to the serial monitor as | |||
// numbers from 0 (maximum reflectance) to 1000 (minimum reflectance) followed | |||
// by the estimated location of the line as a number from 0 to 5000. 1000 means | |||
// the line is directly under sensor 1, 2000 means directly under sensor 2, | |||
// etc. 0 means the line is directly under sensor 0 or was last seen by sensor | |||
// 0 before being lost. 5000 means the line is directly under sensor 5 or was | |||
// last seen by sensor 5 before being lost. | |||
QTRSensors qtr; | |||
const uint8_t SensorCount = 8; | |||
uint16_t sensorValues[SensorCount]; | |||
void setup() | void setup() | ||
{ | { | ||
//Setup Channel A | |||
pinMode(12, OUTPUT); //Initiates Motor Channel A pin | |||
pinMode(9, OUTPUT); //Initiates Brake Channel A pin | |||
//Setup Channel B | |||
pinMode(13, OUTPUT); //Initiates Motor Channel A pin | |||
pinMode(8, OUTPUT); //Initiates Brake Channel A pin | |||
pinMode(A3, OUTPUT); | |||
// configure the sensors | |||
qtr.setTypeRC(); | |||
qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, SensorCount); | |||
qtr.setEmitterPin(16); | |||
delay(500); | delay(500); | ||
pinMode( | //pinMode(A3, OUTPUT); | ||
digitalWrite( | digitalWrite(A3, HIGH); // turn on Arduino's LED to indicate we are in calibration mode | ||
for ( | |||
// 2.5 ms RC read timeout (default) * 10 reads per calibrate() call | |||
// = ~25 ms per calibrate() call. | |||
// Call calibrate() 400 times to make calibration take about 10 seconds. | |||
for (uint16_t i = 0; i < 400; i++) | |||
{ | { | ||
qtr.calibrate(); | |||
} | } | ||
digitalWrite( | digitalWrite(A3, LOW); // turn off Arduino's LED to indicate we are through with calibration | ||
// | // print the calibration minimum values measured when emitters were on | ||
Serial.begin(9600); | Serial.begin(9600); | ||
for ( | for (uint8_t i = 0; i < SensorCount; i++) | ||
{ | { | ||
Serial.print( | Serial.print(qtr.calibrationOn.minimum[i]); | ||
Serial.print(' '); | Serial.print(' '); | ||
} | } | ||
Serial.println(); | Serial.println(); | ||
// | // print the calibration maximum values measured when emitters were on | ||
for ( | for (uint8_t i = 0; i < SensorCount; i++) | ||
{ | { | ||
Serial.print( | Serial.print(qtr.calibrationOn.maximum[i]); | ||
Serial.print(' '); | Serial.print(' '); | ||
} | } | ||
Línea 159: | Línea 212: | ||
delay(1000); | delay(1000); | ||
} | } | ||
void loop() | void loop() | ||
{ | { | ||
// read calibrated sensor values and obtain a measure of the line position from 0 to 5000 | // read calibrated sensor values and obtain a measure of the line position | ||
// from 0 to 5000 (for a white line, use readLineWhite() instead) | |||
uint16_t position = qtr.readLineBlack(sensorValues); | |||
// print the sensor values as numbers from 0 to 1000, where 0 means maximum | |||
// print the sensor values as numbers from 0 to 1000, where 0 means maximum | // reflectance and 1000 means minimum reflectance, followed by the line | ||
// 1000 means minimum reflectance, followed by the line position | // position | ||
for ( | for (uint8_t i = 0; i < SensorCount; i++) | ||
{ | { | ||
Serial.print(sensorValues[i]); | Serial.print(sensorValues[i]); | ||
Serial.print('\t'); | Serial.print('\t'); | ||
} | } | ||
Serial.println(position); | |||
Serial.println(position); | |||
delay(250); | |||
delay( | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Revisión del 18:39 9 abr 2019
Este artículo trata sobre la construcción y programación de un robot que sigue líneas con Arduino y un sensor de infrarojos.
Construcción del Robot
Materiales
El chasis que verás en las fotos es específico, creado a medida por la empresa What's Next? para el proyecto [Robots Boost Skills]. El resto de componentes son genéricos y se pueden comprar Arduinos oficiales, What's Next Yellow o cualquier clon compatible.
Esta es la lista de materiales:
- Chasis que permita 2 ruedas con motor DC analógicos y una rueda delantera.
- 2 Motores DC analógicos con reducción y ruedas.
- Arduino Uno o equivalente.
- 1 Sensor Pololu QTR-8A o QTR-8RC
- Arduino Motor Shield o alguno que tenga el mismo Chip L298
- Baterías, entre 9V y 12V
Construcción del Chasis
En el caso del robot del ejemplo, el chasis tiene todos los elementos necesarios. Si lo tienes que construir, aquí tienes algunos consejos:
- Se recomienda cuidar el centro de gravedad de robot para que no plante rueda y tenga la adherencia necesaria. Por ejemplo, las baterías deberían estar entre las ruedas motrices y la rueda delantera.
- La distancia al suelo del sensor infrarojo es muy importante, ha de estar muy cerca, pero no rozar.
- Hay que dejar espacio para los cables y para poder modificar las conexiones sin necesidad de desmontar todo el robot.
El sensor
En nuestro caso, el sensor QTR-8[A-RC] es un conjunto de 8 emisores y sensores infrarrojos en un mismo circuito. Esto permite una gran precisión ,ya que tienes 8 lecturas cada vez. Estos sensores tienen una distancia recomendada de 3mm y un máximo de 6mm para el QTR-A y 9.5mm para el QTR-8RC.
La salida de los dos sensores es diferente, (analógica o digital), por lo que es importante distinguirlos y decidir cual vamos a usar. En nuestro caso, tenemos el QRT-8RC, por lo que, a partir de aquí, todo el manual se basa en este.
Puesto que vamos a usar 5V para alimentarlo, no es necesario unir los pines de 3.3V Bypass
Podemos conectar el pin LEDON que permite indicar con HIGH, LOW o PWM el estado de los LEDs. Si los apagamos, podemos consumir menos energía cuando no está leyendo.
El QTR8-RC mide la reflectancia con el tiempo entre un estado HIGH y uno LOW.
La lectura típica en el QTR8-RC es la siguiente:
- Encender los LEDs (opcional)
- Poner la linea I/O a una salida y ponerla en HIGH.
- Dejar al menos 10 μs al sensor para que arranque.
- Poner la I/O a Input
- Medir el tiempo que tarda el voltaje en caer esperando a la I/O a que vuelva a LOW.
- Apagar los LEDs (opcional)
Estos pasos se pueden hacer en varias líneas I/O al mismo tiempo. Con mucha reflectividad, el tiempo de bajada a LOW debe ser mínimo. Con poca (superficie negra) el tiempo debe mayor. Se recomienda usar el LEDON para no gastar batería hasta en un 90% del tiempo para lecturas a baja frecuencia, unos (100Hz).
Si se necesitan lecturas a mucha frecuencia, se recomienda que el sensor esté muy cerca del suelo, recomendado 3,5 mm i máximo 9 mm.
Cuanto más lejos peor lecturas y cuanta más luz ambiental peor. Si es necesario, bloquearemos la luz ambiental con cinta aislante o similar.
De esta manera, el esquema de conexiones del robot queda de la siguiente manera:
Programación del robot
Leyendo del sensor
Para que funcione, necesitamos la biblioteca correspondiente. En los últimos Arduino IDE es tan simple como ir al gestor de Bibliotecas y importar la QTRSensors.
La biblioteca funciona tanto para el QTR-8RC como el QTR-8A, pero cambia la manera de configurarlo:
// Crear un objeto para 8 sensores en los pines digitales 2,4,5,6,7,10 y en los analogicos A4 A5
QTRSensors qtr;
qtr.setTypeRC();
qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, 8);
qtr.setEmitterPin(16);
Calibrar los sensores es lo primero que debería hacer el robot. Así, en la rutina de inicialización (setup), se recomienda lanzar este código:
void setup()
{
pinMode(A3, OUTPUT); // LED para indicar que está calibrando
// configure the sensors
qtr.setTypeRC();
qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, SensorCount);
qtr.setEmitterPin(16);
delay(500);
//pinMode(A3, OUTPUT);
digitalWrite(A3, HIGH); // turn on Arduino's LED to indicate we are in calibration mode
// 2.5 ms RC read timeout (default) * 10 reads per calibrate() call
// = ~25 ms per calibrate() call.
// Call calibrate() 400 times to make calibration take about 10 seconds.
for (uint16_t i = 0; i < 400; i++)
{
qtr.calibrate();
}
digitalWrite(A3, LOW); // turn off Arduino's LED to indicate we are through with calibration
// print the calibration minimum values measured when emitters were on
Serial.begin(9600);
for (uint8_t i = 0; i < SensorCount; i++)
{
Serial.print(qtr.calibrationOn.minimum[i]);
Serial.print(' ');
}
Serial.println();
// print the calibration maximum values measured when emitters were on
for (uint8_t i = 0; i < SensorCount; i++)
{
Serial.print(qtr.calibrationOn.maximum[i]);
Serial.print(' ');
}
Serial.println();
Serial.println();
delay(1000);
}
Para leer del sensor, se recomienda usar la función readCalibrated() o read(). Con readCalibrated(), los valores obtenidos serán entre 0 (blanco) y 1000 (negro).
Para la detección de líneas, se usar la función readLine() a la que se puede decir si la línea es blanca o negra. El resultado de esta función es 0 si la línea está dentro o fuera de sensor 0 y 1000*(N-1) para cada sensor. Los valores para 8 sensores pueden ser, por tanto, 0, 1000, 2000 ... 8000 dependiendo de la posición de la línea. Código para analizar los valores que obtiene el sensor con los 8 sensores:
#include <QTRSensors.h>
// This example is designed for use with eight RC QTR sensors. These
// reflectance sensors should be connected to digital pins 3 to 10. The
// sensors' emitter control pin (CTRL or LEDON) can optionally be connected to
// digital pin 2, or you can leave it disconnected and remove the call to
// setEmitterPin().
//
// The setup phase of this example calibrates the sensors for ten seconds and
// turns on the Arduino's LED (usually on pin 13) while calibration is going
// on. During this phase, you should expose each reflectance sensor to the
// lightest and darkest readings they will encounter. For example, if you are
// making a line follower, you should slide the sensors across the line during
// the calibration phase so that each sensor can get a reading of how dark the
// line is and how light the ground is. Improper calibration will result in
// poor readings.
//
// The main loop of the example reads the calibrated sensor values and uses
// them to estimate the position of a line. You can test this by taping a piece
// of 3/4" black electrical tape to a piece of white paper and sliding the
// sensor across it. It prints the sensor values to the serial monitor as
// numbers from 0 (maximum reflectance) to 1000 (minimum reflectance) followed
// by the estimated location of the line as a number from 0 to 5000. 1000 means
// the line is directly under sensor 1, 2000 means directly under sensor 2,
// etc. 0 means the line is directly under sensor 0 or was last seen by sensor
// 0 before being lost. 5000 means the line is directly under sensor 5 or was
// last seen by sensor 5 before being lost.
QTRSensors qtr;
const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];
void setup()
{
//Setup Channel A
pinMode(12, OUTPUT); //Initiates Motor Channel A pin
pinMode(9, OUTPUT); //Initiates Brake Channel A pin
//Setup Channel B
pinMode(13, OUTPUT); //Initiates Motor Channel A pin
pinMode(8, OUTPUT); //Initiates Brake Channel A pin
pinMode(A3, OUTPUT);
// configure the sensors
qtr.setTypeRC();
qtr.setSensorPins((const uint8_t[]){19,18,2,4,5,6,7,10}, SensorCount);
qtr.setEmitterPin(16);
delay(500);
//pinMode(A3, OUTPUT);
digitalWrite(A3, HIGH); // turn on Arduino's LED to indicate we are in calibration mode
// 2.5 ms RC read timeout (default) * 10 reads per calibrate() call
// = ~25 ms per calibrate() call.
// Call calibrate() 400 times to make calibration take about 10 seconds.
for (uint16_t i = 0; i < 400; i++)
{
qtr.calibrate();
}
digitalWrite(A3, LOW); // turn off Arduino's LED to indicate we are through with calibration
// print the calibration minimum values measured when emitters were on
Serial.begin(9600);
for (uint8_t i = 0; i < SensorCount; i++)
{
Serial.print(qtr.calibrationOn.minimum[i]);
Serial.print(' ');
}
Serial.println();
// print the calibration maximum values measured when emitters were on
for (uint8_t i = 0; i < SensorCount; i++)
{
Serial.print(qtr.calibrationOn.maximum[i]);
Serial.print(' ');
}
Serial.println();
Serial.println();
delay(1000);
}
void loop()
{
// read calibrated sensor values and obtain a measure of the line position
// from 0 to 5000 (for a white line, use readLineWhite() instead)
uint16_t position = qtr.readLineBlack(sensorValues);
// print the sensor values as numbers from 0 to 1000, where 0 means maximum
// reflectance and 1000 means minimum reflectance, followed by the line
// position
for (uint8_t i = 0; i < SensorCount; i++)
{
Serial.print(sensorValues[i]);
Serial.print('\t');
}
Serial.println(position);
delay(250);
}
Ejemplo del manual oficial del sensor para un sigue líneas simple con 3 sensores:
void loop()
{
unsigned int sensors[3];
// get calibrated sensor values returned in the sensors array,
// along with the line position.
// position will range from 0 to 2000,
// with 1000 corresponding to the line over the middle sensor.
int position = qtr.readLine(sensors);
// if all three sensors see very low reflectance,
// take some appropriate action for this situation.
if (sensors[0] > 750 && sensors[1] > 750 && sensors[2] > 750)
{
// do something.
// Maybe this means we're at the edge of a course or about to fall off
// a table, in which case, we might want to stop moving, back up, and turn around.
return;
}
// compute our "error" from the line position.
// We will make it so that the error is zero
// when the middle sensor is over the line,
// because this is our goal. Error will range from
// -1000 to +1000.
// If we have sensor 0 on the left and sensor 2 on the right, a reading of
// -1000 means that we see the line on the left
// and a reading of +1000 means we see the
// line on the right.
int error = position - 1000;
int leftMotorSpeed = 100;
int rightMotorSpeed = 100;
if (error < -500) // the line is on the left
leftMotorSpeed = 0; // turn left
if (error > 500) // the line is on the right
rightMotorSpeed = 0; // turn right
// set motor speeds using the two motor speed variables above
}
- (Obsoleto) Manual de la biblioteca del sensor Referencia de la biblioteca
- (Versión 4.) Manual Referencia
- Tutorial en castellano