2010-06-11 4 views
4

Je travaille sur un robot, il fait partie de l'atelier de robotique d'été de notre collège. Nous utilisons des microcontrôleurs C-STAMP d'A-WIT. Je pouvais le faire bouger, tourner à gauche, tourner à droite, reculer. J'ai même réussi à le faire passer le long de la bande noire en utilisant un capteur de contraste.Comment faire bouger mon robot dans un chemin rectangulaire le long du ruban noir?

J'envoie le robot à 30-45 degrés vers le ruban noir sur la table et il s'aligne et commence à se déplacer le long du ruban noir. Il saute un peu, probablement en raison de ma logique de programmation ci-dessous, il exécute une boucle while et vérifie constamment les if, donc il finit par essayer de tourner à gauche et à droite toutes les quelques millisecondes, ce qui explique la secousse. Mais ça va, ça marche, pas aussi lisse que je veux que ça marche mais ça marche! Le problème est que je ne peux pas faire mon robot aller dans un chemin rectangulaire de la bande noire. Dès qu'il atteint le coin de la bande noire, il continue tout droit au lieu de faire un virage à gauche ou à droite.

Mes 2 capteurs sont situés juste en dessous du robot, près de la roue avant, presque au niveau du sol. Il a une valeur "index" allant de 0 à 8. Huit étant le contraste le plus brillant et zéro étant le contraste le plus sombre. Ainsi, lorsque le robot se déplace dans la zone de bande noire, la valeur de l'indice diminue, et sur cette base, j'ai une instruction if disant à mon robot de tourner à gauche ou à droite.

Voici ma tentative. Pour éviter toute confusion, je n'ai pas affiché le code source entier, mais seulement la partie logique responsable du mouvement de mon robot le long de la bande noire.

while(1) { 

    // don't worry about these. 
    // 10 and 9 represent Sensor's PIN location on the motherboard 
    V = ANALOGIN(10, 1, 0, 0, 0); 
    V2 = ANALOGIN(9, 1, 0, 0, 0); 

    // i got this "formula" from the example in my Manual. 
    // V stands for voltage of the sensor. 
    // it gives me the index value of the sensor. 0 = darkest, 8 = lightest. 
    index = ((-(V - 5)/5) * 8 + 0.5); 
    index2 = ((-(V2 - 5)/5) * 8 + 0.5); 

    // i've tweaked the position of the sensors so index > 7 is just right number. 
    // the robot will move anywhere on the table just fine with index > 7. 
    // as soon as it drops to or below 7 (i.e. finds black tape), the robot will 
    // either turn left or right and then go forward. 

    // lp & rp represent left-wheel pin and right-wheel pin, 1 means run forever. 
    // if i change it from 1 to 100, it will go forward for 100ms. 
    if (index > 7 && index2 > 7) 
     goForward(lp, rp, 1); 

    if (index <= 7) { 
     turnLeft(lp, rp, 1); 
     goForward(lp, rp, 1); 
     // this is the tricky part. i've added this code last minute 
      // trying to make my robot turn, but i didn't work. 
     if (index > 4) { 
      turnLeft(lp, rp, 1); 
      goForward(lp, rp, 1); 
     } 
    } 

    else if (index2 <= 7) { 
     turnRight(lp, rp, 1); 
     goForward(lp, rp, 1); 
      // this is also the last minute addition. it's same code as above 
      // but it's for the 2nd sensor. 
     if (index2 > 4) { 
      turnRight(lp, rp, 1); 
      goForward(lp, rp, 1); 
     } 
    } 
} 

J'ai passé la journée entière à essayer de comprendre. J'ai à peu près épuisé toutes les avenues. Demander la solution sur stackoverflow est ma toute dernière option maintenant.

Merci d'avance! Si vous avez des questions sur le code, faites le moi savoir, mais les commentaires doivent être explicites.

Ceci est ma fonction goForward au cas où quelqu'un se demande:

void goForward(BYTE lp, BYTE rp, WORD t) 
{ 
    WORD i; 

    for(i = 0; i < t; i = i + 1){ 
     PULSOUT(lp, 400, 1, 1); 
     PULSOUT(rp, 800, 1, 1); 
     PAUSE(17); 
    } 
} 

MISE À JOUR: Voici ce que je suis venu avec jusqu'à présent. J'ai effacé tous mes si-déclarations que j'ai posté plus tôt et décidé d'écrire la logique à partir de zéro:

// if there's enough bright light in both sensors at the same time 
    // robot will move forward forever. 
    if (index > 7 && index2 > 7) 
     goForward(lp, rp, 1); 

    // but if there's not enough bright light anymore (i.e. reached black tape) 
    // proceed to the else-statement. 
    else { 
     // if left sensor detects the black tape then turn right 
     // if doesn't detect the black tape then keep going forward 
     if (index2 <= 7) 
      turnRight(lp, rp, 1); 
     else 
      goForward(lp, rp, 1); 

     // if right sensor detects the black tape then turn left 
     // if it doesn't detect the black tape then keep going forward 
     if (index <= 7) 
      turnLeft(lp, rp, 1); 
     else 
      goForward(lp, rp, 1); 
    } 

    // The reason for turnLeft and turnRight is to keep robot re-alligning 
    // to the black tape. It will happen so fast (every 1ms) that the jerking 
    // shouldn't even be noticeable. 
+0

Avez-vous essayé chiphacker.com? –

Répondre

3

Vous devez capturer l'occurrence soudaine: [cycle n] "Je vois la bande "-> [cycle n + 1]" Je ne vois pas la bande "qui se produit lorsque vous rencontrez un coin. Un state machine est un bon moyen de gérer ce type de problème. Avec un state machine le code pour un état spécifique est isolé, il ne s'exécute que lorsque l'état est vrai. Cette isolation empêche la "diaphonie" et vous donne un bloc de code connu pour chaque état.

Compte tenu de votre exemple, le flux pourrait être quelque chose comme:

:Loop 

State == Moving forward and on tape. 
    read sensors 
    delta = abs(valueLastCycle - valueThisCycle); 
    if (delta >= bigChangeValue){ 
    // the tape was just gone. 
    // change state and handle this situation. 
    CurrentState = suddenValueChange; 
    }else 
    if (index <= 7) { 
     turnLeft(lp, rp, 1); 
     goForward(lp, rp, 1); 
    else if (index2 <= 7) { 
     turnRight(lp, rp, 1); 
     goForward(lp, rp, 1); 
    } 
    ... 
State == suddenValueChange 
... 
code that handles sudden value change event 
maybe: 
Stop Robot; 
Move backwards slowly until on tape or distance x 
etc... 

Goto Loop 

L'augmentation de la vitesse de balayage peut sembler pour aider .... mais plus vite le robot se déplace plus vite votre vitesse de balayage .... i.e.. Vous pouvez toujours sauter d'une bande -> hors bande, auquel cas votre code actuel patauge.

+0

Intéressant. Merci d'avoir pris le temps d'écrire tout ça. Je vais essayer de convertir ce pseudo-code en code réel dès maintenant, puis le tester lundi. –

+0

Faites un peu de recherche .. mon pseudo code est très incomplet. c'est-à-dire ça craint :) – Rusty

+0

Il semble assez complexe mais soigné. Je n'aurais même pas pensé à obtenir le delta de la distance que le robot a dépassé la bande noire, puis reculer et faire un tour. Je vais mettre à jour ma question maintenant avec ce que j'ai trouvé jusqu'à présent. Je n'ai pas encore implémenté votre pseudo-code, mais j'ai simplement simplifié mon code et je pense que ça va avoir plus de sens maintenant. –

2

Je pense que le goForward immédiatement après la turnLeft/TurnRight « annule » le tournant? Cela dépend de la façon dont le tournage est implémenté.

+0

Cela fonctionne très bien. C'est ce qui fait que ce robot s'aligne avec le ruban noir. Mais il est possible que goForward annule le virage à 90 degrés qu'il est censé faire une fois qu'il atteint le coin. –

+0

Vous avez probablement raison, en mettant une instruction if avant goForward peut résoudre ce problème. –

1

À l'heure actuelle, selon l'apparence de votre code, chaque fois que le robot voit le noir, il avance pour toujours. Je ne suis pas vraiment sûr de la façon dont cela sera mis en œuvre.

En pseudocode, votre code dit:

if you see black 
go forward forever 
if you don't see black 
turn left or right 

Voyez-vous comment votre robot serait aller de l'avant pour toujours avec ce genre de logique? Encore une fois, je n'ai aucune idée de la façon dont l'avenir est mis en œuvre, alors je peux me tromper.

+0

J'ai mis à jour la question avec la fonction goForward. –

+0

C'est exactement ce que je veux faire. Imaginez une grande table carrée contenant un ruban noir de taille moyenne de forme rectangulaire. Ca va bien sur le ruban noir, mais dès qu'il atteint la fin du ruban noir, (il ne voit plus le noir, c'est sur le bois maintenant) il est censé faire un tour, mais ça ne tient pas aller de l'avant et les chutes de la table. –

2

Votre boucle while est-elle suffisamment rapide pour prendre un virage? Si les deux capteurs signalent qu'ils sont sur la bande, et qu'au cours du cycle suivant, les deux capteurs sont hors bande, vous ne pouvez pas le détecter, n'est-ce pas? Le capteur signale les mêmes valeurs (8) pour être sur la bande et hors de la bande?

Essayez d'accélérer le code. Sans voir le code entier, il est difficile de faire une recommandation, mais il semble que vous puissiez évaluer si des déclarations ne sont pas nécessaires. Ajoutez un ELSE après le premier IF, une fois que vous savez que vous allez tout droit.

Il semble que votre implémentation goforward bloque la boucle trop longtemps. 1 ne signifie pas courir éternellement, il fait un passage de la boucle for, puis PAUSE 17 (msec?). A quoi sert la PAUSE? Retirez-le. Cela provoque probablement des secousses et empêche l'entrée de la prochaine série de valeurs de capteur.

+0

La vitesse du processeur est de 40Mhz. J'ai testé le robot de sorte qu'il s'arrête après avoir laissé le ruban noir. Il fait quelques centimètres de plus puis s'arrête ce qui n'est pas trop mal. Qu'est-ce que l'ajout de l'instruction else aboutirait après le premier If? –

+0

Je ne sais pas à quoi sert la PAUSE, je viens de suivre l'exemple du manuel. Je n'ai pas remarqué de saccades pendant qu'il avançait. La raison pour laquelle il est saccadé est parce qu'il aligne gauche, droite, gauche, droite, gauche, droite dès qu'il atteint la bande noire. Je vais essayer de le supprimer lundi, mais je n'ai pas le robot avec moi en ce moment. –

+0

Si vous savez que les deux index sont> 7, aucun d'eux ne peut être <= 7, vous n'avez donc pas besoin de le tester. Je ne comprends toujours pas comment fonctionnent les capteurs de contraste. Est-ce qu'ils rapportent le contraste - pas de contraste, ou rapportent-ils l'obscurité ou la lumière? – cdonner

2

Assurez-vous que votre "plan" est logique avant de vous inquiéter du code. Commencez par déplacer le robot autour de à la main et en observant lorsque les capteurs passent au-dessus des zones en noir et blanc. Essayez de trouver un comportement et simulez-le à la main. Si cela ne fonctionne pas comme vous le souhaitez, vous devez réviser le comportement. Une suggestion: Vous pouvez ajouter d'autres boucles pour vous assurer que si quelque chose ne va pas, le robot se corrige avant de reprendre un comportement normal. (Par exemple, plutôt que de tourner à droite/gauche pendant 100 ms, faites ce comportement tant que les capteurs ont besoin de voir ce qu'il faut.)

Questions connexes