Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola a todos!
Soy bastante nuevo en esto de la electrónica y tengo que reconocer que todavía me peleo con cuestiones básicas. Sin embargo, hace unos meses descubrí el mundo de la robótica y me he propuesto construir un pequeño seguidor de líneas que me sirva como proyecto de aprendizaje. Parto de la base de que es fácil que cometa errores en el diseño, de modo que cualquier comentario y/o sugerencia será bienvenido.
Objetivos
En primer lugar, me he marcado unas líneas básicas a cumplir:
Utilizaré únicamente componentes "through hole" (aunque también me gustaría montar en un futuro una versión con SMT)
Micro ATmega328 montado en placa (tengo un par de Arduinos por aquí, de modo que ya tengo micro + programador...)
Ampliable (aunque no se muy bién a qué, pero obviamente dejaré abierta la posibilidad de usar las conexiones libres del micro)
Bien, creo que mi principal problema será el espacio. Teniendo en cuenta que me gustaría usar una única placa para alojar todos los componentes, la cosa parece muy difícil...
Cuando reciba la placa empezaré con los componentes, los básicos los tengo pero no se si del tamaño y forma adecuados.... me veo llendo con la placa a la tienda para comprobar uno a uno... jajajaja....
Saludos.
furri.
Hola, me encanta el aspecto del robot !!!! Muchas gracias , por poner el esquema !!!!
Un saludo
Bueno, después de muchos sudores, parece que voy consiguiendo que se comporte...
AUG60X5Q0Bc
Ahora me toca perfeccionar giros de 90º y programar el comportamiento en laberintos.
genial....
Ahí va el código:/*
===============================================================
n00b0t_100_lineaPD_012
===============================================================
Conexiones:
irV[0] DIG9 pwm1 DIG5 S2 DIG12
irV[1] ANA1 pwm2 DIG6 led1 DIG13
irV[2] ANA2 dir1 DIG7 buzz DIG11
irV[3] ANA3 dir2 DIG8
irV[4] ANA4
irV[5] ANA5
irV[6] DIG10
===============================================================
irV[3]
irV[4] ### irV[2]
### ### ###
irV[5] ### ### irV[1]
### ###
### ###
irV[6] irV[0]
### ###
### ###
EJEMPLO: pNMax = 50
--------------------------------------------------------------
pN xx 10 20 30 40 50 xx
pE xx -20 -10 0 10 20 xx
===============================================================
*/
// DECLARACIONES
// ############################################################
// ############################################################
// Valores de ajuste.
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
long Kp = 15;
long Kd = 300;
long pNMax =50; // CTE Posición Natural Máxima.
long vMax = 225; // CTE Velocidad Máxima (ABS)
long vStd = 200; // CTE Velocidad Estándar
long pM = 0; // VBLe ajuste de posición (pendiente)
long irFMin = 350; // CTE Filtro para "lectura" sobre blanco
long irFMax = 900; // CTE Filtro para "lectura" sobre negro
// Control.
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
long pN = 3*(pNMax/5); // VBLe Posición Natural. Entre pNMax/5 y pNMax
long pEMax = 2*(pNMax/5); // CTE Posición Error (ABS) Máxima. = 2(pNMax/5)
long pE = 0; // VBLe Posición Error.
long pElast = 0; // VBLe Posición Error Anterior.
//long Kp = vStd/(pEMax - pM); // CTE proporcional
//long Kd = 2*Kp; // CTE derivativa
long irN[6]; // VBLe Peso de Lectura en sensores.
char out = 'C'; // VBLe Posición de salida (R, C o B)
int mD = 0; // VBLe Motor Derecho
int mI = 0; // VBLe Motor Izquierdo
// VBLes de Lecura en sensores.
// El valor de los filtros está en el extremo
// opuesto para que se ajusten en calibración.
long irV[] ={
0,0,0,0,0,0,0};
long irVMax[] = {
1,1,1,1,1,1,1};
long irVMin[] = {
0,1000,1000,1000,1000,1000,0};
int nota = 0; // VBLe Sonido
int boton = 0; // VBLe Botón
// PINes
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
int irPin[] = {
9,1,2,3,4,5,10}; // PINes CNY70
int pwmMDPin = 6; // PIN Enable Motor Derecho
int pwmMIPin = 5; // PIN Enable Motor Izquierdo
int dirMDPin = 8; // PIN Control Motor Derecho
int dirMIPin = 7; // PIN Control Motor Izquierdo
int botonPin = 12; // PIN Botón
int ledPin = 13; // PIN Led Amarillo
int buzzPin = 11; // PIN Buzzer
// SETUP
// ############################################################
// ############################################################
void setup()
{
Serial.begin(9600);
// PINes Mode
int i;
for (i = 0; i < 7; i = i + 1)
{
pinMode(irPin, INPUT);
}
pinMode(pwmMDPin, OUTPUT);
pinMode(pwmMIPin, OUTPUT);
pinMode(dirMDPin, OUTPUT);
pinMode(dirMIPin, OUTPUT);
pinMode(botonPin, INPUT);
pinMode(ledPin, OUTPUT);
// "Peso" de sensores
irN[5]= pNMax/5;
irN[4]= 2*(pNMax/5);
irN[3]= 3*(pNMax/5);
irN[2]= 4*(pNMax/5);
irN[1]= 5*(pNMax/5);
// Buzzer
tone(buzzPin, 335);
delay(200);
tone(buzzPin, 473);
delay(200);
tone(buzzPin, 531);
delay(200);
noTone(buzzPin);
// Pausa / Botón
// *******************************************************
delay(1000);
boton = digitalRead(botonPin);
while (boton == LOW)
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(200);
boton = digitalRead(botonPin);
}
// ****************************************************
// Calibración
motor (-100,100); // 360º
delay(200);
while (millis() < 7000)
{
// irV[0] = digitalRead(irPin[0]);
// irV[6] = digitalRead(irPin[6]);
int i;
for (i = 1; i < 6; i = i + 1)
{
irV = analogRead(irPin);
}
// Señal acústica en función de la lectura del sensor central
nota = map(irV[3], 0, 1023, 100, 1000);
tone(buzzPin, nota, 10);
// Ajustamos los valores máximo y mínimo para los sensores analógicos
for (i = 1; i < 6; i = i + 1)
{
if (irV > irVMax)
{
irVMax = irV;
}
if (irV < irVMin)
{
irVMin = irV;
}
}
}
motor (0,0);
// Buzzer
tone(buzzPin, 335);
delay(200);
tone(buzzPin, 473);
delay(200);
tone(buzzPin, 531);
delay(200);
noTone(buzzPin);
// Pausa / Botón
// ****************************************************
delay(1000);
boton = digitalRead(botonPin);
while (boton == LOW)
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(200);
boton = digitalRead(botonPin);
}
// *******************************************************
}
// LOOP
// ############################################################
// ############################################################
void loop()
{
// Lectura
irV[0] = digitalRead(irPin[0]);
irV[6] = digitalRead(irPin[6]);
int i;
for (i = 1; i < 6; i = i + 1)
{
irV = analogRead(irPin);
}
// Ajuste calibrado
for (i = 1; i < 6; i = i + 1)
{
irV = map(irV, irVMin, irVMax, 1000, 0);
}
// Filtros
for (i = 1; i < 6; i = i + 1)
{
if (irV < irFMin)
{
irV = 0;
}
if (irV > irFMax)
{
irV = 1000;
}
}
// Posición Natural (pN)
pN = ((irV[5]*irN[5]) + (irV[4]*irN[4]) + (irV[3]*irN[3]) + (irV[2]*irN[2])+(irV[1]*irN[1])) / (irV[1]+ irV[2] + irV[3] + irV[4]+ irV[5]);
// Posición de Error (pE)
if (pN >0 ) // Si hay lecturas, calculamos la posición (en Arduino 0/0 = -1)
{
pE = pN - 3*(pNMax/5);
}
else // Si todos los sensores están en blanco, forzamos una posición concreta
{
switch (out)
{
case 'B': // FUERA a la DERECHA
pE = -2*pEMax;
break;
case 'R': // FUERA a la IZQUIERDA
pE= 2*pEMax;
break;
default: // CENTRADO (Forzamos 360)
pE= 4*pEMax;
break;
}
}
// Control
// ===========================================================
if (pE < -pEMax || pE > pEMax) // FUERA
{
digitalWrite(ledPin, HIGH);
}
else if (pE < 0) // A la DERECHA de la línea
{
digitalWrite(ledPin, LOW);
out = 'B';
}
else if (pE > 0) // A la IZQUIERDA de la línea
{
digitalWrite(ledPin, LOW);
out = 'R';
}
else // Perfectamente CENTRADO (==0)
{
digitalWrite(ledPin, LOW);
out = 'C';
}
mI = vStd + pE * Kp + (pE - pElast)* Kd;
mD = vStd - pE * Kp - (pE - pElast)* Kd;
pElast = pE;
motor(mI,mD);
// Control de valores en el monitor serie
// for (i = 6; i > -1; i = i - 1)
// {
// Serial.print(irV);
// Serial.print("t");
// }
//
// Serial.print('#');
// Serial.print("t");
//
// Serial.print(pN);
// Serial.print("t");
// Serial.print(pE);
// Serial.print("t");
// Serial.print(out);
// Serial.print("t");
//
// Serial.print('#');
// Serial.print("t");
//
// Serial.print(Kp);
// Serial.print("t");
// Serial.print(Kd);
// Serial.print("t");
// Serial.print(pE * Kp + (pE - pElast)* Kd);
// Serial.print("t");
//
//
// Serial.print('#');
// Serial.print("t");
//
// Serial.print(mI,DEC);
// Serial.print("t");
// Serial.print(mD,DEC);
// Serial.print("t");
//
// Serial.println("");
}
// FUNCIONES
// ############################################################
// ############################################################
void motor (int vmI, int vmD)
{
if (vmI > 0)
{
digitalWrite(dirMIPin, LOW);
}
else
{
digitalWrite(dirMIPin, HIGH);
}
if (vmD > 0)
{
digitalWrite(dirMDPin, LOW);
}
else
{
digitalWrite(dirMDPin, HIGH);
}
analogWrite(pwmMIPin, constrain(abs(vmI),0,vMax)); //Aplicamos filtro vMax
analogWrite(pwmMDPin, constrain(abs(vmD),0,vMax)); //Aplicamos filtro vMax
}