fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Avisos
Vaciar todo

n00b0t

136 Respuestas
19 Usuarios
0 Reactions
57.9 K Visitas
dip6
Respuestas: 132
 dip6
Topic starter
(@dip6)
Ardero
Registrado: hace 14 años

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:

  • PCB a modo de chasis, con forma circular y dimensiones reducidas (9cm o menos de diámetro)
    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...

    Responder
    135 respuestas
    furri
    Respuestas: 2708
    (@furri)
    Ardero
    Registrado: hace 19 años

    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.

    Responder
    turman
    Respuestas: 98
    (@turman)
    Trusted Member
    Registrado: hace 19 años

    Hola, me encanta el aspecto del robot !!!! Muchas gracias , por poner el esquema !!!!

    Un saludo

    Responder
    dip6
    Respuestas: 132
     dip6
    Topic starter
    (@dip6)
    Ardero
    Registrado: hace 14 años

    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.

    Responder
    furri
    Respuestas: 2708
    (@furri)
    Ardero
    Registrado: hace 19 años

    genial....

    Responder
    dip6
    Respuestas: 132
     dip6
    Topic starter
    (@dip6)
    Ardero
    Registrado: hace 14 años

    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
    }

    Responder
    Página 22 / 28
    Compartir: