SlideShare uma empresa Scribd logo
1 de 48
Baixar para ler offline
1
Programando Robôs
NXT
Usando NXC
(Beta 30 or higher)
(Version 2.2, June 7, 2007)
Por Daniele Benedettelli
Com Revisões de John Hansen
2
Prefácio
Tal como aconteceu para o bom e velho Mindstorms RIS, CyberMaster, e Spybotics,
para libertar todo o potencial das Mindstorms NXT tijolo, você precisa de um ambiente de
programação que é mais útil do que NXT-G, o Nacional Instrumentos LabView-como linguagem
gráfica que vem com NXT retalho set.
NXC é uma linguagem de programação, inventado por John Hansen, que foi
especialmente concebido para a Lego robôs. Se você nunca escreveu um programa antes, não
se preocupe. NXC é realmente fácil de usar e este tutorial vai levá-lo em seus primeiros passos
nesse sentido.
Para tornar ainda mais fácil escrever programas, existe a Bricx Command Center
(BricxCC). Este utilitário permite que você escreva seus programas, para transferi-los para o
robô, para iniciar e detê-los, procure NXT memória flash, converter arquivos sonoros para uso
com o tijolo, e muito mais. BricxCC funciona quase como um processador de texto, mas com
algumas extras. Este tutorial usará BricxCC (versão 3.3.7.16 ou superior), como ambiente de
desenvolvimento integrado (IDE).
Você pode baixá-lo gratuitamente a partir da web, no endereço
http://bricxcc.sourceforge.net/
BricxCC é executado no PC Windows (95, 98, ME, NT, 2K, XP, Vista). NXC A língua
também pode ser usado em outras plataformas. Você pode baixá-lo da página web
http://bricxcc.sourceforge.net/nxc/
A maior parte deste tutorial deve ser igualmente aplicável a outras plataformas, exceto
que você solta algumas das ferramentas incluídas no BricxCC e a cor-codificação. O tutorial foi
atualizado para trabalhar com beta 30 de NXC e versões superiores. Alguns programas da
amostra não irão compilar com versões mais antigas do que beta 30. Como nota lateral, minha
página está cheia de RCX Lego Mindstorms NXT e conteúdo relacionado, incluindo uma
ferramenta para PC comunicar com NXT:
http://daniele.benedettelli.com
Agradecimentos
Muitos agradecimentos vão para John Hansen, cujo trabalho não tem preço!
3
Sumário
Prefácio ....................................................................................................................................... 2
Agradecimentos .............................................................................................................................2
Sumário........................................................................................................................................ 3
1. Gravando o seu primeiro programa...................................................................................... 5
Construir um robô ..........................................................................................................................5
Começando Bricx Command Center..............................................................................................5
Escrever o programa.......................................................................................................................6
Executando o programa .................................................................................................................7
Erros em seu programa...................................................................................................................8
Mudar a velocidade ........................................................................................................................8
Resumo...........................................................................................................................................9
2. Um programa mais interessante ......................................................................................... 10
Tornar voltas ............................................................................................................................... 10
Repetindo comandos ...................................................................................................................10
Adicionando comentários.............................................................................................................11
Resumo ........................................................................................................................................ 12
3. Usando variáveis ................................................................................................................... 13
Passando em uma espiral..............................................................................................................13
Números aleatórios ......................................................................................................................14
Resumo.........................................................................................................................................15
4. Controle estruturas ............................................................................................................... 16
A declaração IF ...........................................................................................................................16
A declaração do............................................................................................................................17
Resumo ........................................................................................................................................ 17
5. Sensores ..............................................................................................................................................18
Esperando por um sensor ............................................................................................................18
Agindo sobre um sensor de Toque ............................................................................................... 19
Sensor de Luz............................................................................................................................... 19
Sensor de Som .............................................................................................................................20
Sensor de Ultra-som .....................................................................................................................21
Resumo ........................................................................................................................................ 22
6. Tarefas e Sub-Rotinas .....................................................................................................................23
Tarefas .........................................................................................................................................23
Sub-Rotinas .................................................................................................................................24
Definindo macros ........................................................................................................................ 25
Resumo ........................................................................................................................................ 26
7. Fazendo música .................................................................................................................................28
Reproduzir arquivos sonoros ....................................................................................................... 28
Reproduzir música ....................................................................................................................... 28
Resumo ........................................................................................................................................ 30
8. Mais informações sobre os motores .............................................................................................31
Parando suavemente ....................................................................................................................31
Comandos avançados ...................................................................................................................31
Controle PID ............................................................................................................................... 33
Resumo ........................................................................................................................................ 34
9. Mais informações sobre os sensores ............................................................................................35
Sensor modalidade e tipo ............................................................................................................35
A rotação sensor...........................................................................................................................36
Colocar vários sensores em uma entrada .....................................................................................37
Resumo ........................................................................................................................................ 38
10. Tarefas Paralelas ............................................................................................................................39
Um programa errado ...................................................................................................................39
Secções críticas e variáveis mutex ............................................................................................... 39
Usando Semáforos ....................................................................................................................... 40
Resumo ........................................................................................................................................ 41
4
11. A comunicação entre robôs ............................................................................................... 42
Mestre - Escravo mensagens ....................................................................................................... 42
Enviando números com aviso ......................................................................................................43
Diretório de comandos .................................................................................................................45
Resumo ........................................................................................................................................ 45
12. Mais comandos ................................................................................................................... 46
Temporizadores ...........................................................................................................................46
Matricial visor .............................................................................................................................46
Sistema Arquivo...........................................................................................................................47
Resumo ........................................................................................................................................ 50
13. Observações finais .........................................................................................................................51
5
1. Gravando o seu primeiro programa
Neste capítulo vou mostrar-lhe como escrever um programa extremamente simples.
Estamos indo para programar um robô para avançar para 4 segundos, depois de recuar mais 4
segundos, e então parar. Não muito espetacular, mas irá apresentar-lhe a idéia de base da
programação. E ele vai te mostrar como isso é fácil. Mas antes que nós possamos escrever um
programa, primeiro precisamos um robô.
Construir um robô
O robô, utilizado ao longo deste tutorial é Tribot, o primeiro veículo que tenha sido
instruído a construir quando tem NXT estabelecidos fora da caixa. A única diferença é que você
deve se conectar a porta um motor direita, esquerda automóvel à porta C e do motor para a
porta B.
Certifique-se de ter instalado corretamente Mindstorms NXT Fantom Drivers que vem com o
seu conjunto.
Começando Bricx Command Center
Nós escrevemos nossos programas usando Bricx Command Center. Iniciá-lo
clicando duas vezes sobre o ícone BricxCC. (Eu assumo você já instalou BricxCC. Se não, fazer o
download a partir do web site (veja o prefácio), e instalá-lo em qualquer diretório que você
gosta. O programa irá pedir a localização do robot. Mudar o robô, e pressione OK. O programa
(o mais provável) encontrar automaticamente o robô. Agora a interface do usuário aparece
como mostrado abaixo (sem o texto guia).
6
A interface parece um editor de texto padrão, com o habitual menu e botões para
abrir e salvar arquivos, impressão arquivos, editar arquivos, etc Mas também existem alguns
menus especiais para compilar e baixar programas para o robô e para obter informações a
partir do robô. Você pode ignorar estes para o momento.
Vamos agora escrever um novo programa. Então, pressione o botão Novo para criar
um arquivo novo e vazio janela.
Escrever o programa
Agora digite o seguinte programa:
task main()
{
OnFwd(OUT_A, 75);
OnFwd(OUT_C, 75);
Wait(4000);
OnRev(OUT_AC, 75);
Wait(4000);
Off(OUT_AC);
}
Pode parecer um pouco complicado num primeiro momento, vamos analisá-lo assim.
Programas em NXC composto de tarefas. Nosso programa tem apenas uma tarefa,
chamado principal. Cada programa deverá ter uma chamada tarefa principal, que é a que vai
ser executada pelo robô. Você vai aprender mais sobre a missão no capítulo VI. Uma tarefa
consiste de uma série de comandos, também chamados de declarações. Há cerca de
parênteses as declarações tal que, é claro que todos eles pertencem a esta tarefa. Cada
declaração termina com um ponto e vírgula. Desta forma, é evidente uma declaração onde
acaba e onde começa a próxima declaração. Então, parece uma tarefa, em geral, como segue:
task main()
7
{
statement1;
statement2;
…
}
Nosso programa tem seis declarações. Olhemos para um deles no momento:
OnFwd(OUT_A, 75);
Esta declaração diz o robô para iniciar uma produção, ou seja, o motor ligado à saída
marcada Ano NXT, para avançar. O número seguinte apresenta a velocidade do motor a 75%
da velocidade máxima.
OnFwd(OUT_C, 75);
Mesma declaração, mas agora começamos a motor C. Após estas duas declarações,
ambos os motores estão funcionando, e os robôs se move em frente.
Wait(4000);
Agora é tempo para esperar por um tempo. Esta afirmação diz-nos a esperar por 4
segundos.O argumento, isto é, o número entre parênteses, indica o número de 1 / 1000 de um
segundo: assim que você pode dizer muito claramente ao programa como tempo para esperar.
Para a 4 segundos, o programa está dormindo e o robô continua a avançar.
OnRev(OUT_AC, 75);
O robô tem agora longe suficiente para dizer que para avançar na direção inversa, ou
seja, para trás. Note que nós pode definir ambos os motores de uma vez OUT_AC usando
como argumento. Nós também podíamos ter combinado das duas primeiras declarações desta
forma.
Wait(4000);
Novamente vamos esperar por 4 segundos.
Off(OUT_AC);
E finalmente nós dois motores switch off.
Esse é todo o programa. Move-se ambos os motores em frente por 4 segundos,
em seguida, para trás, para 4 segundos, e finalmente mudá-las.
Você, provavelmente já notou as cores quando a digitação no programa. Eles
aparecem automaticamente. As cores e estilos utilizado pelo editor quando se realiza
sintaxe highlighting são personalizáveis.
Executando o programa
Depois de ter escrito um programa, ele precisa ser compilado (ou seja,
transformada em código binário que o robô pode compreender e executar) e enviado
para o robô usando o cabo USB ou BT dongle (chamados de "descarregar" os
programas).
Aqui você pode ver o botão que lhe permite (da esquerda para a direita)
compilar, faça o download, executar e parar o programa.
Pressione o botão e segundo, assumindo que você fez que não há erros na
digitação quando o programa, ele será correctamente compilados e baixadas. (Se houver
erros em seu programa, você será notificado, ver abaixo.)
Agora você pode executar o seu programa. Para isso, vá ao menu Meus
Ficheiros OnBrick, Software arquivos, e execute 1_simple programa. Lembre-se:
software NXT arquivos em arquivos têm o mesmo nome como fonte NXC arquivo.
Além disso, para obter o programa ser executado automaticamente, pode utilizar o
atalho CTRL + F5 ou depois de fazer o download do programa que você pode
pressionar o botão verde correr.
Será que o robot fazer o que você esperava? Se não, verifique fio conexões.
Erros em seu programa
8
Ao digitar nos programas, há uma hipótese razoável que você faça alguns erros.
Os avisos do compilador erros e relatá-los a você, na parte inferior da janela, como na
figura a seguir:
Ela seleciona automaticamente o primeiro erro (nós digitado incorretamente o
nome do motor). Quando há mais erros, você pode clique sobre as mensagens de erro de
ir para elas. Note que muitas vezes erros no início do programa causar outros erros em
outros lugares. Então, melhor apenas corrigir alguns erros do primeiro e, em seguida,
compile o programa novamente. Observe também que a sintaxe de ajuda imenso a evitar
erros. Por exemplo, na última linha digitada of nós, em vez de Off. Porque este é um
comando esconhecido, não é destacada.
Existem também erros que não são encontrados pelo compilador. Se tivéssemos
digitado OUT_B isto causar o mal motor a girar. Se o seu robô exibe um
comportamento inesperado, o mais provável é algo de errado em seu programa.
Mudar a velocidade
Como você notou, o robô movido bastante rápido. Para alterar a velocidade que
você só mudar o segundo parâmetro no interior parênteses. O poder é um número entre
0 e 100. 100 é o mais rápido, 0 significa parar (servo motores irá NXT mantenha
posição). Aqui está uma nova versão do nosso programa em que o robô se move
lentamente:
task main()
{
OnFwd(OUT_AC, 30);
Wait(4000);
OnRev(OUT_AC, 30);
Wait(4000);
Off(OUT_AC);
}
Resumo
9
Neste capítulo você escreveu seu primeiro programa no NXC, utilizando
BricxCC. Agora você deve saber qual o tipo de um programa, como transferir-lo para o
robô e como deixar o robô executar o programa. BricxCC pode fazer muitas mais
coisas. Para saber mais sobre eles, leia a documentação que vem com ele. Este tutorial
irá abordar essencialmente com a língua e só NXC mencionar características da
BricxCC quando você realmente precisa deles.
Você também aprendeu alguns aspectos importantes da língua NXC. Primeiro de
tudo, você aprendeu que cada programa tem uma tarefa que a chamada principal é
sempre executado pelo robô. Também você aprendeu o básico motor quatro comandos:
OnFwd (), OnRev () e off (). Finalmente, você aprendeu sobre a Wait ()
declaração.
2. Um programa mais interessante
10
O nosso primeiro programa não foi tão incrível. Então, vamos tentar torná-la
mais interessante. Faremos isso em uma série de passos, introduzindo alguns aspectos
importantes da nossa linguagem de programação NXC.
Tornar voltas
Você pode fazer seu robô turno, parando ou invertendo a direção de um dos dois
motores. Aqui está um exemplo. Digite a sua senha, fazer o download para o seu robô e
deixar correr. Deve dirigir um pouco e então faça um grau 90-direita turno.
task main()
{
OnFwd(OUT_AC, 75);
Wait(800);
OnRev(OUT_C, 75);
Wait(360);
Off(OUT_AC);
}
Você pode ter que experimentar alguns ligeiramente diferentes números
superiores a 500 na segunda Esperar () comando para fazer um 90
grau turno. Isso depende do tipo de superfície sobre a qual o robô executa. Ao invés de
mudar isso no programa é mais fácil de usar um nome para este número. Em NXC você
pode definir valores constantes conforme mostrado na programa seguinte.
#define MOVE_TIME 1000
#define TURN_TIME 360
task main()
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
Off(OUT_AC);
}
As duas primeiras linhas definem duas constantes. Estas podem agora ser
utilizados em todo o programa. Definindo constantes é boa por dois motivos: ela torna o
programa mais legível, e é mais fácil de alterar os valores. Note que BricxCC dá
declarações a definir sua própria cor. Como veremos no capítulo VI, você pode também
definir as coisas outros que não constantes.
Repetindo comandos
Vamos agora tentar escrever um programa que faz com que o robô em uma
unidade quadrada. Indo em uma praça significa: condução em frente, virar 90 graus,
condução em frente de novo, virar 90 graus, etc Podíamos repetir o referido pedaço de
Código quatro vezes, mas isso pode ser feito muito mais fácil com a repeat declaração.
11
#define MOVE_TIME 500
#define TURN_TIME 500
task main()
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
Off(OUT_AC);
}
O número dentro da repetição da declaração parênteses indica quantas vezes o
seu código dentro parênteses deve ser repetido. Note que, no programa acima, também
as declarações travessão. Isso não é necessário, mas torna o programa mais legível.
Como um último exemplo, vamos fazer o robô unidade 10 vezes em um quadrado. Aqui
está o programa:
#define MOVE_TIME 1000
#define TURN_TIME 500
task main()
{
repeat(10)
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
}
Off(OUT_AC);
}
Existe agora uma declaração repetir dentro da outra. Chamamos isso de "nested"
repetir declaração. Você pode repetir ninho declarações o quanto quiser. Tome um
cuidado olhar para os suportes e as indentação utilizada no programa. O
tarefa começa no primeiro escalão e termina no último. A primeira repetição declaração
começa no segundo escalão e termina na quinta. A repetição aninhada declaração
começa no terceiro escalão, e termina na quarta. Como você vê os parênteses
sempre vêm em pares, e a peça entre os parênteses que travessão.
Adicionando comentários
Para tornar o programa ainda mais legível, é bom para acrescentar alguns
comentários a ele. Sempre que você colocar / / em um
linha, o resto da linha é ignorado e pode ser usado para comentários. Um longo
comentário pode ser colocada entre / * e * /. Comentários são destacadas na sintaxe
BricxCC. A programação completa pode parecer como se segue:
/* 10 SQUARES
This program make the robot run 10 squares
*/
12
#define MOVE_TIME 500 // Time for a straight move
#define TURN_TIME 360 // Time for turning 90 degrees
task main()
{
repeat(10) // Make 10 squares
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, 75);
Wait(TURN_TIME);
}
}
Off(OUT_AC); // Now turn the motors off
}
Resumo
Neste capítulo você aprendeu a utilização da declaração e repetir o uso de
comentário. Também você viu a função aninhados de parênteses e ao uso de indentação.
Com tudo o que sabemos até agora você pode fazer o robô mover todos juntamente
tipos de caminhos. É um bom exercício para tentar escrever algumas variações dos
programas neste capítulo antes continuar com o próximo capítulo.
3. Usando variáveis
13
Variáveis forma um aspecto muito importante de todas as linguagens de
programação. As variáveis são locais na memória que pode armazenar um valor.
Podemos utilizar esse valor em locais diferentes e podemos mudá-la. Vamos descrever a
utilização de variáveis usando um exemplo.
Passando em uma espiral
Suponhamos que queremos adaptar o programa acima de forma a que o robot
movimentações em uma espiral. Isto pode ser alcançado , tirando o sono do que tempo
de maior circulação para cada lado direto. Isto é, queremos aumentar o valor de
MOVE_TIME cada vez. Mas como podemos fazer isso? MOVE_TIME é uma
constante e, portanto, não pode ser alterado. Nós necessitamos de uma variável vez.
Variáveis podem ser facilmente definida no NXC. Aqui está a espiral programa.
#define TURN_TIME 360
int move_time; // define a variable
task main()
{
move_time = 200; // set the initial value
repeat(50)
{
OnFwd(OUT_AC, 75);
Wait(move_time); // use the variable for sleeping
OnRev(OUT_C, 75);
Wait(TURN_TIME);
move_time += 200; // increase the variable
}
Off(OUT_AC);
}
O interessante linhas são indicados com os comentários. Em primeiro lugar,
definir uma variável, digitando a palavra-chave int seguido por um nome que
escolhemos. (Normalmente usamos minúscula letras para a variável nomes e letras
maiúsculas para constantes, mas isso não é necessário). O nome deve iniciar com uma
letra, mas pode conter os dígitos e sublinhado assinar. Não são permitidos outros
símbolos. (O mesmo se aplicava aos constantes, tarefa nomes, etc) A palavra está para o
int inteiro. Apenas números inteiros podem ser armazenados na mesma. Na segunda
linha vamos atribuir o valor 200 para a variável. A partir deste momento em diante,
sempre que você usar a variável, o seu valor será 200. Agora segue a repetir em loop
que usamos a variável para indicar a hora de dormir e, no final do ciclo que aumentar o
valor da variável por 200. Então, a primeira vez que o robô dorme 200 ms, 400 ms, o
segundo tempo, o terceiro time 600 ms, e assim ligado.
Além de acrescentar valor a uma variável que também pode multiplicar uma
variável com um número usando *=, subtrair usando -= e dividir usando / =. (Note que,
para a divisão do resultado é arredondado para o número inteiro mais próximo.) Você
também pode adicionar uma variável para o outro, e anote mais complicado expressões.
O próximo exemplo, não têm qualquer efeito em seu robô de hardware, uma vez que
não sabemos como usar o visor NXT ainda!
int aaa;
int bbb,ccc;
int values[];
14
task main()
{
aaa = 10;
bbb = 20 * 5;
ccc = bbb;
ccc /= aaa;
ccc -= 5;
aaa = 10 * (ccc + 3); // aaa is now equal to 80
ArrayInit(values, 0, 10); // allocate 10 elements = 0
values[0] = aaa;
values[1] = bbb;
values[2] = aaa*bbb;
values[3] = ccc;
}
Nota sobre as primeiras duas linhas que podemos definir múltiplas variáveis em
uma linha. Nós também podíamos ter combinado tudo três deles em uma linha. A
variável denominada valores é uma matriz, ou seja, uma variável que contém mais de
um Número: um array pode ser indexada com um número dentro de colchetes. Em NXC
inteiro matrizes são declaradas assim:
int name[];
Então, esta linha aloca 10 elementos initializing eles a 0.
ArrayInit(values, 0, 10);
Números aleatórios
Em todos os programas acima, definimos exatamente o que o robô era suposto
fazer. Mas as coisas se tornam muito mais interessante quando o robô vai fazer coisas
que não sabemos. Queremos que haja alguma aleatoriedade na moções. Em NXC você
pode criar números aleatórios. O seguinte programa usa isso para deixar a unidade em
torno de um robô forma aleatória. É constantemente unidades encaminha para um valor
aleatório de tempo e, em seguida, faz uma aleatória turno.
int move_time, turn_time;
task main()
{
while(true)
{
move_time = Random(600);
turn_time = Random(400);
OnFwd(OUT_AC, 75);
Wait(move_time);
OnRev(OUT_A, 75);
Wait(turn_time);
}
}
O programa define duas variáveis e, em seguida, atribui-lhes números aleatórios.
Random(600)significa um aleatória número entre 0 e 600 (o valor máximo não está
incluído no intervalo de números devolvida). Cada vez Random chamar os números
serão diferentes.
Note que pudéssemos evitar o uso das variáveis por escrito directamente por
exemplo, Wait(Random(600)).
Você também verá um novo tipo de laço aqui. Em vez que a utilização da
declaração repetir que escrevemos while (true). O tempo declaração reitera as
declarações abaixo dela, enquanto a condição entre parênteses é a verdade. A especial
palavra verdadeira é sempre verdadeira, então as declarações entre os parênteses são
repetidas indefinidamente (ou, pelo menos até que você pressione
o cinzento escuro botão NXT). Você vai aprender mais sobre a declaração enquanto no
Capítulo IV.
15
Resumo
Neste capítulo você aprendeu sobre o uso de variáveis e matrizes. Você pode
declarar do que outros tipos de dados int: short, long, byte, bool e string.
Você também aprendeu a criar números aleatórios, de modo que você pode dar o
robô um comportamento imprevisível.
Finalmente vimos o uso da comunicação a fazer, enquanto um ciclo infinito que
vai para sempre.
4. Controle estruturas
16
Nos capítulos anteriores vimos a repetir, e enquanto declarações. Estas
declarações controlar a forma como os outros declarações do programa são executados.
Eles são chamados de "estruturas de controlo". Neste capítulo veremos alguns
outras estruturas de controlo.
A declaração IF
Às vezes você deseja que uma determinada parte do seu programa só é
executado em determinadas situações. Neste caso, o declaração, se for utilizado.
Permitam-me dar um exemplo. Vamos mudar novamente o programa que temos vindo a
trabalhar com tão longe, mas com um novo giro. Queremos que o robô de condução ao
longo de uma linha recta e então fazer a esquerda ou à direita turno. Para isso
precisamos de números aleatórios novamente. Nós escolher um número aleatório que é
positivo ou negativo. Se o número é inferior a 0 fazemos uma curva à direita, caso
fizermos uma esquerda turno. Aqui está o programa:
#define MOVE_TIME 500
#define TURN_TIME 360
task main()
{
while(true)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
if (Random() >= 0)
{
OnRev(OUT_C, 75);
}
else
{
OnRev(OUT_A, 75);
}
Wait(TURN_TIME);
}
}
A declaração se parece um pouco como o tempo declaração. Se a condição entre
parênteses é a verdade a parte entre os parênteses é executado. Caso contrário, a parte
entre os parênteses depois da palavra o resto é executado. Permitir nos olhar um pouco
melhor a condição que nós usamos. Ele lê Random() >= 0. Isto significa que Random()
deve ser maior que ou igual a 0 para tornar a condição verdadeira. Você pode comparar
valores de formas diferentes. Aqui estão os mais importantes:
== Igual a
< Menor que
<= Menor ou igual a
> Maior que
> = Maior que ou igual a
! = Não igual a
Você pode combinar condições usar &&, que significa "e", ou ||,, o que significa
"ou". Aqui estão alguns exemplos de condições:
true sempre verdade
false nunca verdade
ttt != 3 verdade quando ttt não é igual a 3
(ttt >= 5) && (ttt <= 10) verdade quando ttt oscila entre 5 e 10
(aaa == 10) || (bbb == 10) verdade se aaa ou bbb forem igual a 10
Note que a declaração se tem duas partes. A parte imediatamente após a
condição, que é executado quando o condição é verdadeira, assim como a parte após a
outra, que é executada quando a condição é falsa. A palavra-chave e outra a parte depois
17
que são opcionais. Assim, você pode omiti-los, se não há nada a fazer quando a
condição é falsa.
A declaração do
Existe uma outra estrutura de controlo, a fazer declaração. Tem a seguinte
forma:
do
{
statements;
}
while (condition);
As declarações entre os parênteses após a fazer parte são executadas enquanto a
condição é verdadeira. A condição tem a mesma forma como no caso acima descrito
declaração. Aqui está um exemplo de um programa. O robô é executado aleatoriamente
em torno de 20 segundos e depois pára.
int move_time, turn_time, total_time;
task main()
{
total_time = 0;
do
{
move_time = Random(1000);
turn_time = Random(1000);
OnFwd(OUT_AC, 75);
Wait(move_time);
OnRev(OUT_C, 75);
Wait(turn_time);
total_time += move_time;
total_time += turn_time;
}
while (total_time < 20000);
Off(OUT_AC);
}
Note também que fazer a declaração comporta quase o mesmo que o tempo
declaração. Mas enquanto que na declaração do condição é testada antes de executar as
declarações, enquanto que nos fazem menção a condição é testada no final.
Por enquanto a declaração, as declarações poderiam nunca ser executado, mas para
fazer a declaração que são executadas em menos uma vez.
Resumo
Neste capítulo, vimos duas novas estruturas de controlo: a declaração IF e a
declaração DO. Juntamente com o declaração e repetir a declaração enquanto eles são
as declarações que controlam a maneira pela qual o programa é executada. É muito
importante que você entenda o que eles fazem. Então, melhor tentar mais alguns
exemplos yourself antes de continuar.
5. Sensores
Claro que você pode se conectar sensores para fazer o robô NXT reagir a
eventos externos. Antes que eu posso mostrar como a isso, temos de mudar o robô um
18
pouco, adicionando um toque sensor. Tal como antes, siga as instruções para Tribot
construir o pára-choque dianteiro.
Ligue o sensor de toque de entrada 1 sobre o NXT.
Esperando por um sensor
Comecemos com um simples programa no qual o robô drives em frente até que
ele acerta algo. Aqui está:
task main()
{
SetSensor(IN_1,SENSOR_TOUCH);
OnFwd(OUT_AC, 75);
until (SENSOR_1 == 1);
Off(OUT_AC);
}
Existem duas linhas importante aqui. A primeira linha do programa informa ao
robô que tipo de sensor que usamos. IN_1 é o número da entrada para que o sensor
ligado. O outro sensor insumos são chamados IN_2, IN_3 e IN_4. SENSOR_TOUCH
indica que este é um toque sensor. Para o sensor de luz iríamos utilizar
SENSOR_LIGHT. Depois de especificar o tipo de sensor, o programa muda de ambos
os motores e começa o robô em movimento frente. O próximo mapa é uma construção
muito útil. Ele espera até que o estado está entre os parênteses VERDADEIRO. Esta
condição indica que o valor do sensor SENSOR_1 deve ser 1, o que significa que o
sensor é pressionada. Desde que o sensor não está pressionado, o valor é 0. Portanto,
esta declaração aguarda até que o sensor seja pressionado.
Então, desligue o motor e para a tarefa está concluída.
Agindo sobre um sensor Toque
19
Vamos agora tentar fazer o robô evitar obstáculos. Sempre que o robô atinge um
objeto, nós deixá-lo voltar um pouco, fazer uma vez, e em seguida continuar. Aqui está
o programa:
task main()
{
SetSensorTouch(IN_1);
OnFwd(OUT_AC, 75);
while (true)
{
if (SENSOR_1 == 1)
{
OnRev(OUT_AC, 75); Wait(300);
OnFwd(OUT_A, 75); Wait(300);
OnFwd(OUT_AC, 75);
}
}
}
Tal como no exemplo anterior, primeiro indicar o tipo de sensor. Em seguida, o
robô começa avançar. No loop infinito enquanto estamos constantemente a testar se o
sensor é tocado, e, em caso afirmativo, mover de volta para 300 ms, vire à direita para
300 ms, e, em seguida, continuar em frente novamente.
Sensor Luz
Além de tocar o sensor, você também terá um sensor luz, um som e um sensor
digital com sensores ultra-sônicos Mindstorms NXT sistema. O sensor de luz pode ser
acionado para emitir luz ou não, assim você pode medir a quantidade de luz refletida ou
luz ambiente em uma determinada direção. Medir a luz reflectida é particularmente útil
quando tornando um robô seguir uma linha no chão. Isto é o que vamos fazer no
próximo exemplo. Para continuar com a experimentos, acabamento Tribot edifício.
Conecte sensor de luz de entrada 3, sensor de som de entrada 2 e sensores ultra-sônicos
entrada para 4, conforme indicado por instruções.
Temos também o teste com o bloco faixa preta que vem com o NXT set. O
princípio básico da linha seguinte é que o robô continua a tentar ficar direita, na
20
fronteira com a linha preta, girando fora da linha, se a luz nível é muito baixo (e sensor
está no meio da linha) e virando para a linha, se o sensor está fora da faixa e detecta um
elevado nível luz. Aqui está um programa muito simples fazer linha seguinte com uma
única luz limiar valor.
#define THRESHOLD 40
task main()
{
SetSensorLight(IN_3);
OnFwd(OUT_AC, 75);
while (true)
{
if (Sensor(IN_3) > THRESHOLD)
{
OnRev(OUT_C, 75);
Wait(100);
until(Sensor(IN_3) <= THRESHOLD);
OnFwd(OUT_AC, 75);
}
}
}
O programa, primeiro porto 3 configura como uma luz sensor. Em seguida põe-
se o robot para avançar e vai para um loop infinito. Sempre que a função valor é maior
que 40 (usamos aqui uma constante tal que este pode ser adaptado fácil, porque depende
muito do entorno luz) que reverter um motor e aguarde até que estamos no bom
caminho novamente.
Como você vai ver quando você executar o programa, o movimento não é muito
bom. Tente adicionar um Wait(100) comando até antes do comando para fazer o robô
mover melhor. Note que o programa não funciona para que se deslocam no sentido anti-
horário. Para ativar o movimento ao longo arbitrária um caminho muito mais
complicado programa é necessário.
Para ler luz ambiente com intensidade levou off, configure o sensor do seguinte
modo:
SetSensorType(IN_3,IN_TYPE_LIGHT_INACTIVE);
SetSensorMode(IN_3,IN_MODE_PCTFULLSCALE);
ResetSensor(IN_3);
Som sensor
Usando o som sensor pode transformar o seu caro NXT fixado em um chocalho!
Nós estamos indo para escrever um programa que espera por um som alto, e impulsiona
o robô até que outro som é detectado. Fixe o sensor sonoro para a porta 2, conforme
descrito no manual Tribot instruções.
#define THRESHOLD 40
#define MIC SENSOR_2
task main()
21
{
SetSensorSound(IN_2);
while(true)
{
until(MIC > THRESHOLD);
OnFwd(OUT_AC, 75);
Wait(300);
until(MIC > THRESHOLD);
Off(OUT_AC);
Wait(300);
}
}
Primeiro, definir um THRESHOLD constante e um alias para SENSOR_2; na tarefa
principal, que configure a porta 2 do ler dados a partir do som sensor e nós começamos
um ciclo para sempre.
Usando a declaração até que o programa espera que o nível sonoro a ser superior
ao limiar optamos: nota SENSOR_2que não é apenas um nome, mas uma macro que
retorna o valor lido som do sensor. Se ocorrer um som alto, o robô começa a ir direto
até que outro som pára-lo.
A espera declarações foram inseridas, porque caso contrário, o robô seria iniciar
e parar imediatamente: na verdade, o NXT é tão rápido que não tem tempo para
executar linhas entre os dois até declarações. Se você tentar comentar para fora a
primeira ea segunda esperar, você vai entender isso melhor. Uma alternativa para a
utilização de até de esperar por eventos é ao mesmo tempo, é suficiente para colocar
dentro dos parênteses uma condição complementar, por exemplo,
while(MIC <= THRESHOLD).
Não há muito mais para saber sobre NXT sensores analógicos, basta lembrar que
ambos os sensores luz e som dar-lhe uma leitura de 0 a 100.
Sensor ultra-sônico
Ultrasonico sensor funciona como um sonar: grosso modo, ele envia um estouro
de ondas ultra-sônicas e mede o tempo necessário para as ondas de ser reflectida de
volta pelo objeto em vista. Este é um sensor digital, o que significa que tem uma
embutido dispositivo integrado para analisar e enviar dados. Com este novo sensor que
você pode fazer um robô ver e evitar um obstáculo antes de bater-lo (como é para tocar
sensor).
#define NEAR 15 //cm
task main()
{
SetSensorLowspeed(IN_4);
while(true)
{
OnFwd(OUT_AC,50);
while(SensorUS(IN_4)>NEAR);
Off(OUT_AC);
OnRev(OUT_C,100);
Wait(800);
}
}
O programa inicializa porta 4 para ler dados do sensor digital E.U.; então
executa sempre um loop onde vai robôs recta até algo mais perto do que NEAR cm (15
centímetros no nosso exemplo) está em vista, em seguida, backups um pouco e começa
frente novamente.
Resumo
22
Neste capítulo você viu como trabalhar com todos os sensores incluídos no NXT
set. Vimos também until e while comandos são úteis quando se utiliza sensores.
Eu recomendo que você escreva um número de programas por si no seu ponto.
Você tem todos os ingredientes para dar seus robôs comportamento bastante complicada
agora: tentar traduzir em NXC os programas mais simples mostrado na NXT retalho
software Robô Centro guia de programação.
6. Tarefas e Sub-Rotinas
23
Até agora todos os nossos programas consistiu de apenas uma tarefa. Mas NXC
programas podem ter múltiplas funções. É também possível colocar pedaços de código
no âmbito dos chamados sub-rotinas que você pode usar em lugares diferentes em seu
programa.
Usando funções e sub-rotinas torna os programas mais fáceis de compreender e
mais compacta. Neste capítulo, irá analisar as várias possibilidades.
Tarefas
NXC Um programa consiste em mais de 255 tarefas, cada uma delas tem um
nome único. A tarefa principal chamado deve sempre existe, porque esta é a primeira
tarefa a ser executada. As demais tarefas serão executadas somente quando executando
uma tarefa diz que elas sejam executadas ou estão expressamente prevista na principal;
principal tarefa deve terminar antes de poderem iniciar. A partir desse momento, ambas
as funções estão sendo executados simultaneamente.
Deixe-me mostrar o uso de tarefas. Queremos fazer um programa em que o robô
em torno de unidades em praças, como antes. Mas quando se atinge um obstáculo que
deve reagir a ela. É difícil fazer isso em uma tarefa, uma vez que o robô deve fazer duas
coisas ao mesmo tempo: cerca de unidade (isto é, mudar motores ligar e desligar no
tempo) e relógio de sensores. Então é melhor usar duas funções para isso, uma tarefa
que se move em praças, sendo que o outro que reage à sensores. Aqui está o programa.
mutex moveMutex;
task move_square()
{
while (true)
{
Acquire(moveMutex);
OnFwd(OUT_AC, 75); Wait(1000);
OnRev(OUT_C, 75); Wait(500);
Release(moveMutex);
}
}
task check_sensors()
{
while (true)
{
if (SENSOR_1 == 1)
{
Acquire(moveMutex);
OnRev(OUT_AC, 75); Wait(500);
OnFwd(OUT_A, 75); Wait(500);
Release(moveMutex);
}
}
}
task main()
{
Precedes(move_square, check_sensors);
SetSensorTouch(IN_1);
}
A principal tarefa só define o tipo de sensor e, em seguida, inicia ambas as
outras tarefas, adicionando-os na fila do agendador; após isto, principal tarefa termina.
Tarefa move_square move o robô sempre nas praças. Tarefa check_sensors controlos se
o toque sensor é empurrado e, nesse caso, leva o robô afastado obstáculo.
É muito importante lembrar que iniciou funções estão executando no mesmo
momento e isso pode levar a resultados inesperados, se ambas as funções estão tentando
mover motores, uma vez que se destinam a fazer.
Para evitar esses problemas, é declarado um estranho tipo de variável, mutex
(que corresponde a exclusão mútua): nós pode agir sobre este tipo de variáveis só com a
24
aquisição e lançamento funções, escrita crítica pedaços de código entre estas funções,
garantindo que apenas uma tarefa em um tempo pode ter um controlo total sobre
motores.
Estas variáveis são de tipo mutex chamado Semáforos e esta técnica é chamada
de programação concorrente programação; este argumento é descrito em pormenor no
capítulo 10.
Sub-Rotinas
Às vezes você precisa do mesmo pedaço de código em vários lugares em seu
programa. Neste caso você pode colocar o pedaço de código em uma sub-rotina e dar-
lhe um nome. Agora você pode executar esse pedaço de código, simplesmente chamar a
sua nome de dentro de uma tarefa. Vejamos um exemplo.
sub turn_around(int pwr)
{
OnRev(OUT_C, pwr); Wait(900);
OnFwd(OUT_AC, pwr);
}
task main()
{
OnFwd(OUT_AC, 75);
Wait(1000);
turn_around(75);
Wait(2000);
turn_around(75);
Wait(1000);
turn_around(75);
Off(OUT_AC);
}
Neste programa, temos definida uma sub-rotina que faz com que o robô gire em
torno de seu centro. A principal tarefa exige a sub-rotina três vezes. Note que nós
chamamos a sub-rotina escrevendo seu nome e passar uma numéricos argumento é
escrito dentro seguintes parênteses. Se uma sub-rotina não aceita argumentos, basta
adicionar parênteses sem nada dentro deles.
Por isso, parece o mesmo que muitos dos comandos que temos visto.
O principal benefício da sub-rotinas é que eles são armazenados apenas uma vez
no NXT e isso economiza memória. Mas quando sub-rotinas são curtos, pode ser
melhor usar funções inline vez. Estes não são armazenados separadamente, mas é
copiado em cada local são usados. Este utiliza mais memória, mas não há limite para o
número de funções inline. Eles pode ser declarado como segue:
inline int Name( Args )
{
//body;
return x*y;
}
Definindo e chamando funções inline vai exactamente da mesma forma que com
sub-rotinas. Portanto, o exemplo acima, usando inline funções, tem o seguinte aspecto:
inline void turn_around()
{
OnRev(OUT_C, 75); Wait(900);
25
OnFwd(OUT_AC, 75);
}
task main()
{
OnFwd(OUT_AC, 75);
Wait(1000);
turn_around();
Wait(2000);
turn_around();
Wait(1000);
turn_around();
Off(OUT_AC);
}
No exemplo acima, podemos fazer o tempo para transformar um argumento da
função, como nos seguintes exemplos:
inline void turn_around(int pwr, int turntime)
{
OnRev(OUT_C, pwr);
Wait(turntime);
OnFwd(OUT_AC, pwr);
}
task main()
{
OnFwd(OUT_AC, 75);
Wait(1000);
turn_around(75, 2000);
Wait(2000);
turn_around(75, 500);
Wait(1000);
turn_around(75, 3000);
Off(OUT_AC);
}
Note que no parêntese para trás o nome da função inline especificamos o
argumento da (s) função. Em neste caso, indicar que o argumento é um inteiro (existem
algumas outras opções) e que seu nome é turntime. Quando há mais argumentos, você
deve separá-los com vírgulas. Note que em NXC, sub é o mesmo nulos, que também
pode ter outras funções tipo de retorno do que nula, também pode retornar inteiro ou
string valores para o chamador: para obter mais informações, consulte o Guia NXC.
Definindo macros
Existe ainda uma outra forma de dar pequenos pedaços de código de um nome.
Você pode definir macros em NXC (a não ser confundidas com as macros em
BricxCC). Vimos antes que possamos definir constantes, usando # define, por dando-
lhes um nome. Mas na verdade podemos definir qualquer pedaço de código. Aqui é o
mesmo programa novamente, mas agora usando uma macro para se virando.
#define turn_around 
OnRev(OUT_B, 75); Wait(3400);OnFwd(OUT_AB, 75);
task main()
{
26
OnFwd(OUT_AB, 75);
Wait(1000);
turn_around;
Wait(2000);
turn_around;
Wait(1000);
turn_around;
Off(OUT_AB);
}
Após a declaração # define a palavra turn_around defende o texto por trás dele.
Agora, sempre que você digita turn_around, este é substituído pelo presente texto. Note
que o texto deve estar em uma linha. (Na verdade, existem maneiras de colocando uma
# define declaração em várias linhas, mas isto não é recomendado.)
Definir declarações são realmente muito mais poderoso. Eles também podem ter
argumentos. Por exemplo, podemos colocar a tempo para ativar como um argumento na
declaração. Aqui está um exemplo em que se definem quatro macro's, um para mover
em frente, um para mover para trás, um a virar à esquerda e um de virar à direita. Cada
um tem dois argumentos: a velocidade e o tempo
#define turn_right(s,t) 
OnFwd(OUT_A, s);OnRev(OUT_B, s);Wait(t);
#define turn_left(s,t) 
OnRev(OUT_A, s);OnFwd(OUT_B, s);Wait(t);
#define forwards(s,t) OnFwd(OUT_AB, s);Wait(t);
#define backwards(s,t) OnRev(OUT_AB, s);Wait(t);
task main()
{
backwards(50,10000);
forwards(50,10000);
turn_left(75,750);
forwards(75,1000);
backwards(75,2000);
forwards(75,1000);
turn_right(75,750);
forwards(30,2000);
Off(OUT_AB);
}
É muito útil para definir essas macros. Faz o seu código mais compacto e
legível. Além disso, você pode obter mais facilmente alterar o seu código quando você
e.g. mudar as conexões dos motores.
Resumo
Neste capítulo você viu o uso de funções, subrotinas, funções inline, e macros.
Eles têm várias utilizações.
Tarefas normalmente executado no mesmo momento e cuidar de coisas
diferentes que têm de ser feito no mesmo momento. Subrotinas são úteis quando
grandes pedaços de código deve ser utilizado em locais diferentes na mesma tarefa.
Inline funções são úteis quando pedaços de código deve ser utilizado um muitos
lugares diferentes em diferentes tarefas, mas usam mais memória. Finalmente macros
são muito úteis para pequenos pedaços de código que deve ser utilizado um lugares
diferentes. Eles também podem ter parâmetros, tornando-os ainda mais útil.
Agora que você tem trabalhado através dos capítulos até aqui, você tem todas as
habilidades que você precisa para fazer seu robô fazer as coisas complicadas. Os outros
capítulos neste tutorial ensinar-vos acerca de outras coisas que são importantes apenas
em determinadas aplicações.
7. Fazendo música
27
O NXT tem um alto-falante que pode reproduzir tons e mesmo ficheiros de som.
Trata-se, em especial útil quando você quero fazer o NXT dizer-lhe que algo está
acontecendo. Mas também pode ser engraçado para que o robô faça música ou falar ao
mesmo tempo que corre ao redor.
Reproduzir arquivos sonoros
BricxCC tem incorporado um elemento de utilidade para converter. Wav em.
RSO arquivos acessíveis via menu Som conversão.Ferramentas Então você pode
armazenar. RSO arquivos sonoros sobre NXT memória flash usando outro utilitário, o
NXT memória navegador NXT Explorer) e reproduzi-los com o comando(Ferramentas
PlayFileEx(filename, volume, loop?)
Os seus argumentos são sólidos filename, volume (um número de 0 a 4), e loop:
este último argumento é definido como 1 (TRUE) se quiser que o arquivo a ser furado
ou 0 (FALSO) se você quiser reproduzi-lo somente uma vez.
#define TIME 200
#define MAXVOL 7
#define MINVOL 1
#define MIDVOL 3
#define pause_4th Wait(TIME)
#define pause_8th Wait(TIME/2)
#define note_4th 
PlayFileEx("! Click.rso",MIDVOL,FALSE); pause_4th
#define note_8th 
PlayFileEx("! Click.rso",MAXVOL,FALSE); pause_8th
task main()
{
PlayFileEx("! Startup.rso",MINVOL,FALSE);
Wait(2000);
note_4th;
note_8th;
note_8th;
note_4th;
note_4th;
pause_4th;
note_4th;
note_4th;
Wait(100);
}
Este belo programa reproduz a primeira música que você pode iniciar já sabe,
então usa a outra norma clique som para jogar "barbear e um corte de cabelo" jingle que
fez Roger Rabbit go crazy! As macros são realmente úteis, neste caso, para simplificar a
notação das principais tarefas: tentar modificar as configurações de volume para
adicionar acentos na melodia.
Reproduzir música
Para reproduzir um tom, você pode utilizar o comando PlayToneEx(frequency,
duration, volume, loop?)
Tem quatro argumentos. A primeira é a frequência em Hertz, o segundo, a
duração (em 1 / 1000 de um segundo, como no aguardar o comando), e o último volume
são um loop como antes. PlayTone(frequency, duration) também pode ser utilizada;
neste caso, o volume é o fixado pelo NXT um menu, eo circuito está desativado.
Aqui está uma tabela de frequências útil:
Sound 3 4 5 6 7 8 9
B 247 494 988 1976 3951 7902
A# 233 466 932 1865 3729 7458
A 220 440 880 1760 3520 7040 14080
28
G# 415 831 1661 3322 6644 13288
G 392 784 1568 3136 6272 12544
F# 370 740 1480 2960 5920 11840
F 349 698 1397 2794 5588 11176
E 330 659 1319 2637 5274 10548
D# 311 622 1245 2489 4978 9956
D 294 587 1175 2349 4699 9398
C# 277 554 1109 2217 4435 8870
C 262 523 1047 2093 4186 8372
Tal como acontece com o caso de PlayFileEx, o NXT, não espere que a nota
para terminar. Portanto, se você usar vários tons na uma linha, então você teve melhor
acrescentar (pouco mais) entre em esperar comandos. Aqui está um exemplo:
#define VOL 3
task main()
{
PlayToneEx(262,400,VOL,FALSE); Wait(500);
PlayToneEx(294,400,VOL,FALSE); Wait(500);
PlayToneEx(330,400,VOL,FALSE); Wait(500);
PlayToneEx(294,400,VOL,FALSE); Wait(500);
PlayToneEx(262,1600,VOL,FALSE); Wait(2000);
}
Você pode criar peças de música muito facilmente utilizando o Brick Piano que
faz parte do BricxCC.
Se quiser ter o NXT ouvir música enquanto estiver dirigindo por aí, melhor usar
uma tarefa separada para ele. Aqui você tem uma exemplo de um programa onde o
bastante estúpido NXT drives para frente e para trás, constantemente fazer música.
task music()
{
while (true)
{
PlayTone(262,400); Wait(500);
PlayTone(294,400); Wait(500);
PlayTone(330,400); Wait(500);
PlayTone(294,400); Wait(500);
}
}
task movement()
{
while(true)
{
OnFwd(OUT_AC, 75); Wait(3000);
OnRev(OUT_AC, 75); Wait(3000);
}
}
task main()
{
Precedes(music, movement);
}
Resumo
Neste capítulo você aprendeu a deixar o NXT reproduzir sons e música.
Também você viu como usar uma tarefa para música.
8. Mais informações sobre os motores
29
Há um número adicional de motor comandos que você pode usar para controlar
os motores com mais precisão. Neste capítulo, discuti-las: ResetTachoCount, Costa
(float), OnFwdReg, OnRevReg, OnFwdSync, OnRevSync, RotateMotor,
RotateMotorEx, e conceitos básicos PID.
Paragem suave
Quando você usa o Off() comando, o servo motor pára imediatamente,
travagem do eixo e exploração posição.
Também é possível parar o motor em uma maneira mais suave, não utilizando o
freio. Para esta utilização Float() ou Coast() comando mediocremente, simples que
retira o poder fluir a motor. Aqui está um exemplo. Primeiro o robô pára de usar os
freios; próxima sem utilizar os travões. Observe a diferença. Na verdade, a diferença é
muito pequena especial para esse robô. Mas ela faz uma grande diferença para alguns
outros robôs.
task main()
{
OnFwd(OUT_AC, 75);
Wait(500);
Off(OUT_AC);
Wait(1000);
OnFwd(OUT_AC, 75);
Wait(500);
Float(OUT_AC);
}
Comandos Avançados
Os comandos OnFwd() e OnRev() são as rotinas mais simples para mover
motores.
O NXT servomotores possuem um codificador built-in que permite que você
controle precisamente veio posição e velocidade; NXT firmware implementa um PID
(Proportional Integrative Derivative) de ciclo fechado controlador para controlar
motores' posição e velocidade usando encoders como feedback.
Se você deseja que seu robô para ir perfeitamente reto, você pode usar um
recurso que faz a sincronização selecionados casal de motores para funcionar em
conjunto e esperar uns dos outros, no caso um deles seja abrandado, ou mesmo
bloqueado, em um mesma forma, você pode definir um par de motores para funcionar
em conjunto em sincronia, com uma percentagem de orientar a virar à esquerda,
direita ou girar no lugar, mas sempre mantendo sinc. Existem muitos comandos para
libertar servomotores «plenos poderes! OnFwdReg(‘ports',‘speed',‘regmode') leva o
motor especificado por" portos ", em 'velocidade' poder Modo de aplicação do
regulamento que pode ser tanto OUT_REGMODE_IDLE, OUT_REGMODE_SPEED
OUT_REGMODE_SYNC. INACTIVIDADE Se for selecionado, não PID regulamento serão
aplicadas; VELOCIDADE se está seleccionado o modo, o NXT regulamenta único
motor para obter uma velocidade constante, mesmo quando a carga no motor varia,
finalmente, se SYNC é selecionada, o casal de motores especificados por "portos"
mover em sincronia como explicado antes.
OnRevReg()funciona como o precedente comando, inverter direção.
task main()
{
OnFwdReg(OUT_AC,50,OUT_REGMODE_IDLE);
30
Wait(2000);
Off(OUT_AC);
PlayTone(4000,50);
Wait(1000);
ResetTachoCount(OUT_AC);
OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED);
Wait(2000);
Off(OUT_AC);
PlayTone(4000,50);
Wait(1000);
OnFwdReg(OUT_AC,50,OUT_REGMODE_SYNC);
Wait(2000);
Off(OUT_AC);
}
Este programa mostra bem diferente regulamentação, se tentar parar de rodas
segurando o robô em suas mãos: em primeiro lugar (Modo de espera), parando uma
roda que você não vai notar nada; depois (modo de velocidade), a tentativa de abrandar
um roda, você verá que o motor NXT aumenta o poder de superar a sua espera, a tentar
manter a velocidade constante; finalmente (SINC mode), parando uma roda fará com
que o outro para uma parada, à espera que o bloqueou um.
OnFwdSync(‘ports',‘speed',‘turnpct') é o mesmo que OnFwdReg() no
comando SYNC modalidade, mas agora você também pode especificar a «turnpct«
direcção percentual (de -100 a 100).
OnRevSync() é o mesmo que antes, simplesmente inverter o motor da direcção.
O programa seguinte mostra estes comandos: tente mudar direcção número para ver
como se comporta.
task main()
{
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,0);
Wait(1000);
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,20);
Wait(1000);
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,-40);
Wait(1000);
PlayTone(5000,30);
OnRevSync(OUT_AC,50,90);
Wait(1000);
Off(OUT_AC);
}
Finalmente, motores pode ser configurado para ligar a um número limitado de
graus (lembre-se que uma volta completa é 360 °).
Para ambos os seguintes comandos, você pode agir em direção a motor da
mudança, quer o sinal da velocidade ou o sinal do ângulo: assim, se a velocidade eo
ângulo tem mesmo sinal, motor irá correr em frente, se o seu sinal é oposto, o motor irá
correr para trás.
RotateMotor(‘ports',‘speed',‘degrees')gira eixo do motor especificada pelo
'portas' por um' graus' ângulo em 'velocidade' poder (no intervalo 0-100).
task main()
{
RotateMotor(OUT_AC, 50,360);
RotateMotor(OUT_C, 50,-360);
}
RotateMotorEx(‘ports',‘speed',‘degrees',‘turnpct',‘sync', 'stop')is an
extension of theprecedent command, that lets you synchronize two motors (e.g. OUT_AC)
specifying a ‘turnpct'steering percentage (from -100 to 100) and a boolean flag ‘sync'
31
(that can be set to true or false). It also lets youspecify whether the motors should brake
after the angle of rotation has completed using the boolean flag 'stop'.
task main()
{
RotateMotorEx(OUT_AC, 50, 360, 0, true, true);
RotateMotorEx(OUT_AC, 50, 360, 40, true, true);
RotateMotorEx(OUT_AC, 50, 360, -40, true, true);
RotateMotorEx(OUT_AC, 50, 360, 100, true, true);
}
Controle PID
NXT firmware implementa uma digital PID (proporcional integrativo
derivados) controlador para regular servomotores' posição e velocidade com precisão.
Este tipo de controlador é um dos mais simples ainda mais eficaz em circuito fechado
feedback controlador automação é conhecida, e é frequentemente utilizado.
Nas palavras grosseiras, funciona assim (vou falar sobre regulação para uma
posição discreta tempo controlador):
Seu programa dá o controlador um ponto de referência R (t) para alcançar e
que acciona o motor com um comando U (t), medição da sua posição Y (t), com o built-
in codificador e calcula um erro E (t) = R (t) - Y (t): aqui é a razão pela qual é chamado
de "ciclo fechado controlador", porque a posição de saída Y (t) é trazida de volta para o
controlador de entrada para calcular o erro. O controlador transforma o erro E (t) para o
comando U (t) de modo:
U(t) = P(t) + I(t) + D(t), where
P(t) = KP·E(t),
I(t) = KI·( I(t–1) + E(t) )
and D(t) = KD·(E(t) – E(t –1)).
Pode parecer muito difícil para um iniciante, mas vou tentar explicar o
mecanismo da melhor forma que posso.
O comando é a soma de três contribui, a parte proporcional P (t), a
integradora parte I (t) e do derivado parte D (t).
P (t) faz com que o controlador em tempo rápido, mas não garanto um erro
nulo no equilíbrio;
I (t) dá "memória" para o controlador, no sentido em que assume traços de
erros acumulados e compensa eles, com a garantia de um erro zero de equilíbrio;
D (t), dá "futuro previsão" para o controlador (como derivação em
matemática), acelerando a resposta.
Eu sei que isto ainda pode ser confuso, consideram que todo acadêmico
livros foram escritos sobre este argumento! Mas ainda podemos experimentá-lo on-line,
com os nossos NXT tijolo! O programa simples de corrigir as coisas para a memória é o
seguinte.
#define P 50
#define I 50
#define D 50
task main()
{
RotateMotorPID(OUT_A, 100, 180, P, I, D);
Wait(3000);
}
O RotateMotorPID(port,speed, angle, Pgain,Igain,Dgain) permitem-lhe
mover um motor configuração diferente PID ganhos a partir do padrão queridos. Tente
definir os seguintes valores
32
(50,0,0): o motor não girar 180 °, exactamente, uma vez que um erro
continua descompensada
(0, x, x): sem a parte proporcional, o erro é muito grande (40,40,0): há uma
superação, o que significa eixo do motor se move para além do set point e então vira
costas
(40,40,90): uma boa precisão e aumento do tempo (tempo para chegar ao set
point)
(40,40200): o eixo oscilar, pois derivado ganho é muito alto
Experimente outros valores para descobrir como estes ganhos influência um
desempenho do motor.
Resumo
Neste capítulo você aprendeu sobre o avançado motor comandos
disponíveis: float (), Costa () que parar o motor suavemente; OnXxxReg (), e
OnXxxSync () que permite o controlo sobre motores feedback 'velocidade e
sincronização; RotateMotor () e RotateMotorEx () são usados para ligar o motor veio
por um número exacto de graus. Você Aprendi algo sobre controle PID também, não foi
uma explicação exaustiva, mas talvez tenha causado um pouco de curiosidade em você:
pesquisa na web sobre ela!
9. Mais informações sobre os sensores
No capítulo V, discutimos os aspectos básicos do uso de sensores. Mas há
muito mais que você pode fazer com sensores. Em este capítulo vamos discutir a
diferença entre o modo de sensor e sensor tipo, vamos ver como usar os antigos
compatível RCX sensores, anexando-os a utilizar Lego NXT conversor cabos.
Sensor modalidade e tipo
O SetSensor () comando que vimos antes realmente faz duas coisas: que
define o tipo de sensor, e ele define o modo em que o sensor atua. Ao definir o modo eo
tipo de um sensor separadamente, você pode controlar o comportamento do sensor de
forma mais precisa, o que é útil para determinadas aplicações. O tipo de sensor é
definido com o comando SetSensorType (). Existem muitos tipos diferentes, mas vou
relatório os principais: SENSOR_TYPE_TOUCH, que é o toque sensor,
SENSOR_TYPE_LIGHT_ACTIVE, que é o sensor de luz (com LED ligado),
SENSOR_TYPE_SOUND_DB, que é o som sensor, e
SENSOR_TYPE_LOWSPEED_9V, que é o sensor ultra-sônico. Definir o tipo de
sensor é especialmente importante para indicar se o sensor tem poder (por exemplo,
para acender conduziram à luz sensor), ou para indicar que o NXT sensor é digital e
deve ser lido através do protocolo serial I2C. É possível utilizar o antigo RCX sensor
com NXT: SENSOR_TYPE_TEMPERATURE, para o sensor de temperatura, luz
SENSOR_TYPE_LIGHT para antigos sensor, SENSOR_TYPE_ROTATION para
RCX rotação sensor (este tipo será discutido mais tarde).
O modo do sensor é definido com o comando SetSensorMode (). Há oito
modos diferentes. O mais é um importante SENSOR_MODE_RAW. Neste modo, o
valor que você começa quando a verificação do sensor é um número entre 0 e 1023. É o
valor bruto produzido pelo sensor. O que isso significa que depende do próprio sensor.
Para exemplo, para tocar um sensor, quando o sensor não é empurrada para o valor está
perto de 1023. Quando estiver plenamente empurrado, ele está perto de 50. Quando é
33
empurrado parcialmente o valor varia entre 50 e 1000. Portanto, se você definir um
sensor de toque modo raw você pode realmente saber se é tocado parcialmente. Quando
o sensor é um sensor luz, o valor varia de cerca de 300 (muito leve) a 800 (muito
escuro). Isto dá um valor muito mais precisas do que usando o SetSensor () comando.
Para mais informações, consulte o Guia NXC Programação. O segundo modo é
SENSOR_MODE_BOOL sensor. Neste modo, o valor é 0 ou 1. Quando o valor bruto é
superior a 562 o valor é 0, caso contrário, ela é de 1. SENSOR_MODE_BOOL é o
modo padrão para um toque sensor, mas pode ser utilizado para outros tipos,
descartando informação analógica. Os modos SENSOR_MODE_CELSIUS e
SENSOR_MODE_FAHRENHEIT são úteis somente com sensores de temperatura e dê
a temperatura indicada no maneira. SENSOR_MODE_PERCENT transforma o valor
bruto em um valor entre 0 e 100. SENSOR_MODE_PERCENT é o modo padrão para
uma luz sensor. SENSOR_MODE_ROTATION só é utilizado para a rotação sensor
(ver abaixo).
Existem dois outros modos interessantes: SENSOR_MODE_EDGE e
SENSOR_MODE_PULSE. Eles contam transições, isto é, as mudanças de uma baixa
para um alto valor bruto ou oposto. Por exemplo, quando você tocar um toque sensor
presente provoca uma transição de alto a baixo valor bruto. Quando você libertá-lo,
obtém uma transição a outra direção. Quando você define o sensor de modo
SENSOR_MODE_PULSE, só a partir de transições de baixa a alta são contadas. Assim,
cada toque e liberação da conta para um sensor toque. Quando você define o sensor de
modo SENSOR_MODE_EDGE, ambas as transições são contadas. Assim, cada toque e
liberação da touch sensor para duas contagens. Então você pode usar esse recurso para
contar quantas vezes um toque sensor é empurrado. Ou você pode usá-lo em
combinação com um sensor de luz contam como muitas vezes uma (forte) lâmpada é
ligada e desligada. Claro, quando você está contando arestas ou pulsos, deverá ser
capazes de definir o contador volta a 0. Para isso, você use o comando ClearSensor (),
que apura o contador para o indicado sensor. Vejamos um exemplo. O seguinte
programa usa um sensor toque para orientar o robô. Ligue o toque sensor com um longo
fio de uma entrada. Se tocar o sensor rapidamente duas vezes o robot se move em
frente. Por que você lhe toque quando ele pára de se mover.
task main()
{
SetSensorType(IN_1, SENSOR_TYPE_TOUCH);
SetSensorMode(IN_1, SENSOR_MODE_PULSE);
while(true)
{
ClearSensor(IN_1);
until (SENSOR_1 > 0);
Wait(500);
if (SENSOR_1 == 1) {Off(OUT_AC);}
if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);}
}
}
Note que primeiro definir o tipo de sensor e, em seguida, o modo. Parece
que isto é essencial porque mudar O tipo também afecta o modo.
A rotação sensor
34
A rotação é um sensor muito útil tipo de sensor: é um encoder óptico, quase
o mesmo que construir um dentro NXT servomotores. A rotação sensor contém um
buraco através do qual você pode colocar um eixo, cujo parente posição angular é
medido. Uma rotação completa do eixo contagens 16 passos (-16 ou se ele rodar a outra
forma),
o que significa uma resolução 22,5 graus, muito áspera relação ao 1-grau resolução do
servomotor. Este antigo tipo de rotação sensor pode ser ainda útil para monitorar um
eixo, sem a necessidade de um motor de resíduos; também considerar que
usando um motor como codificador requer uma grande quantidade de torque para movê-
lo, enquanto antigo rotação sensor é muito fácil de rodar.
Se você precisar de mais finas resolução superior a 16 passos por sua vez,
você sempre pode usar artes mecanicamente para aumentar o número de carrapatos por
turno.
Seguinte exemplo é herdado do antigo tutorial para RCX.
Uma aplicação padrão é ter dois sensores conectados à rotação duas rodas
do robô que você controle com os dois motores. Para um movimento rectilíneo quiser
para ligar as duas rodas igualmente rápido. Infelizmente, os motores normalmente não
são executados em exatamente a mesma velocidade. Utilizando sensores de rotação que
você pode ver que uma roda voltas mais rápidas. Em seguida, você pode interromper
temporariamente a que o motor (melhor usar Float ()) até que ambos os sensores dar a
mesma valor novamente. O seguinte programa faz isso. Ele simplesmente permite que o
robô em uma unidade da linha recta. Para usá-lo, mudar seu robot, ligando os dois
sensores de rotação das duas rodas. Ligue a entrada dos sensores 1 e 3.
task main()
{
SetSensor(IN_1, SENSOR_ROTATION); ClearSensor(IN_1);
SetSensor(IN_3, SENSOR_ROTATION); ClearSensor(IN_3);
while (true)
{
if (SENSOR_1 < SENSOR_3)
{
OnFwd(OUT_A, 75); Float(OUT_C);
}
else if (SENSOR_1 > SENSOR_3)
{
OnFwd(OUT_C, 75); Float(OUT_A);
}
else
{
OnFwd(OUT_AC, 75);
}
}
}
O programa, primeiro indica que ambos os sensores são sensores rotação, e
redefine os valores a zero. Em seguida é iniciado um loop infinito. No laço que
verifique se o sensor duas leituras são iguais. Se eles são o robô simplesmente jogadas
frente. Se um é maior, o correto motor está parado até duas leituras são novamente
iguais.
É evidente que isto só é um programa muito simples. Você pode estender
isso para fazer o robô unidade distâncias exatas, ou a deixar é preciso fazer muito gira.
Colocar vários sensores em uma entrada
35
Um pouco de renúncia é necessária no início desta secção! Devido à nova
estrutura de melhores NXT sensores e 6 -- fios cabos, não é fácil como antes (como foi
para RCX) para conectar mais sensores para o mesmo porto. Na minha honesta
opinião, a única confiável (e fácil de fazer) seria pedido para construir um toque sensor
analógico multiplexer de usar em combinação com um conversor cabo. A alternativa é
um complexo multiplexer digital que pode gerenciar I2C comunicação com NXT, mas
este não é definitivamente uma solução acessível para os principiantes.
O NXT tem quatro entradas para ligar sensores. Quando você quiser tornar
mais complicado robôs (e que você comprou alguns extras sensores), este poderá não
ser suficiente para você. Felizmente, com alguns truques, você pode ligar duas (ou ainda
mais) sensores para uma entrada.
O mais fácil é para ligar dois sensores de toque uma entrada. Se um deles
(ou ambos), é abordado o valor for 1, caso contrário é 0. Você não pode distinguir os
dois, mas às vezes isso não é necessário. Por exemplo, quando você colocar um toque
sensor na parte dianteira e um na parte de trás do robô, você sabe o que é tocado um
baseado no direcção do robot está dirigindo pol Mas você também pode definir o modo
de entrada para as matérias-primas (veja acima). Agora você pode começar muito mais
informações. Se você é sortudo, o valor é pressionada quando o sensor não é a mesma
para ambos os sensores. Se é este o caso, você pode realmente distinguir entre os dois
sensores. E quando ambos são pressionadas você obterá um grande menor valor (cerca
de 30) para que você também pode detectar isto. Você também pode ligar um toque
sensor e um sensor de luz uma entrada (RCX sensores apenas). Defina o tipo de luz
(caso o sensor de luz não irá funcionar). Defina o modo de matérias-primas. Neste caso,
quando o toque sensor é empurrada para você obter um valor bruto inferior a 100. Caso
não seja empurrada para você obter o valor de o sensor de luz, que nunca é inferior a
100. O programa seguinte utiliza esta ideia. O robô deve ser equipado com um sensor
luz apontando para baixo, e um pára-choques à frente ligado a um sensor toque. Conecte
a entrada de ambos 1. O robô terá unidade em torno de aleatoriamente dentro de uma
luz área. Quando o sensor de luz vê uma linha escura (valor bruto> 750) que vai voltar
um pouco. Quando o toque sensor toque algo (valor bruto inferior a 100) que faz o
mesmo. Aqui está o programa:
mutex moveMutex;
int ttt,tt2;
task moverandom()
{
while (true)
{
ttt = Random(500) + 40;
tt2 = Random();
Acquire(moveMutex);
if (tt2 > 0)
{
OnRev(OUT_A, 75);
OnFwd(OUT_C, 75);
Wait(ttt);
}
else
{
OnRev(OUT_C, 75);
OnFwd(OUT_A, 75);
Wait(ttt);
}
ttt = Random(1500) + 50;
OnFwd(OUT_AC, 75);
Wait(ttt);
Release(moveMutex);
}
}
task submain()
36
{
SetSensorType(IN_1, SENSOR_TYPE_LIGHT);
SetSensorMode(IN_1, SENSOR_MODE_RAW);
while (true)
{
if ((SENSOR_1 < 100) || (SENSOR_1 > 750))
{
Acquire(moveMutex);
OnRev(OUT_AC, 75); Wait(300);
Release(moveMutex);
}
}
}
task main()
{
Precedes(moverandom, submain);
}
Espero que o programa é muito claro. Existem duas tarefas. Tarefa
moverandom faz com que o robô se deslocar em um aleatória maneira. A principal
tarefa primeiro começa moverandom, estabelece que o sensor e, em seguida, espera por
alguma coisa para acontecer. Se o sensor leitura fica demasiado baixo (tocar) ou muito
alta (fora da área branca) ele pára a movimentos aleatórios, faz o backup de um pouco, e
começar a aleatórias jogadas novamente.
Resumo
Neste capítulo, temos visto uma série de questões adicionais sobre sensores.
Vimos como separadamente para definir o tipo e modo de um sensor e como isso
poderia ser utilizado para obter informações aditamentos. Aprendemos como utilizar o
rotação sensor. E vimos como múltiplos sensores podem ser conectados a uma entrada
do NXT. Todos estes truques são extremamente útil quando se mais complicada robôs.
Sensores sempre desempenhar um papel crucial lá.
10. tarefas paralelas
Como já foi indicado antes, em NXC tarefas são executadas em simultâneo,
ou em paralelo à medida que as pessoas geralmente dizem. Isto é extremamente útil.
Nos sensores permite que você preste atenção a uma tarefa em outra tarefa enquanto se
move em torno do robô, e ainda uma outra tarefa desempenha algumas músicas. Mas,
paralelamente tarefas também podem causar problemas. Uma tarefa pode interferir com
outro.
Um programa errado
Considere o seguinte programa. Aqui uma tarefa unidades ao redor do robô
em praças (como fizemos tantas vezes antes) e a segunda tarefa verifica a tocar sensor.
Quando o sensor é tocado, desloca-se um pouco para trás, e faz um 90-grau turno.
task check_sensors()
{
while (true)
{
if (SENSOR_1 == 1)
{
OnRev(OUT_AC, 75);
Wait(500);
OnFwd(OUT_A, 75);
Wait(850);
37
OnFwd(OUT_C, 75);
}
}
}
task submain()
{
while (true)
{
OnFwd(OUT_AC, 75); Wait(1000);
OnRev(OUT_C, 75); Wait(500);
}
}
task main()
{
SetSensor(IN_1,SENSOR_TOUCH);
Precedes(check_sensors, submain);
}
Este é, provavelmente parecido com um programa perfeitamente válido.
Mas se você executá-lo você provavelmente irá encontrar alguns um comportamento
inesperado. Experimente o seguinte: Faça o robô tocar alguma coisa enquanto ela
estiver rodando. Ela vai começar a ir volta, mas logo se move em frente de novo,
batendo o obstáculo. A razão para isto é que as tarefas podem interferir. A seguir está a
acontecer. O robô está rodando direito, isto é, a primeira tarefa é, em sua segunda sono
declaração. Agora, o robô atinge o sensor. Ela vai começar para trás, mas em que
momento, a tarefa principal é pronto com sono e move o robô envia novamente; para o
obstáculo. A segunda tarefa está dormindo a esta momento por isso não irá detectar a
colisão. Isto não é claramente o comportamento que gostaríamos de ver. O problema é
que, enquanto a segunda tarefa está dormindo nós não percebemos que a primeira tarefa
era ainda em execução, e que as suas acções interferem com as ações da segunda tarefa.
Secções críticas e variáveis mutex
Uma maneira de resolver este problema é ter a certeza de que, em qualquer
momento, apenas uma tarefa é conduzir o robô. Esta foi a abordagem que tomou no
capítulo VI. Permitam-me repetir o programa aqui.
mutex moveMutex;
task move_square()
{
while (true)
{
Acquire(moveMutex);
OnFwd(OUT_AC, 75); Wait(1000);
OnRev(OUT_C, 75); Wait(850);
Release(moveMutex);
}
}
task check_sensors()
{
while (true)
{
if (SENSOR_1 == 1)
{
Acquire(moveMutex);
OnRev(OUT_AC, 75);Wait(500);
OnFwd(OUT_A, 75); Wait(850);
Release(moveMutex);
}
}
}
task main()
{
SetSensor(IN_1,SENSOR_TOUCH);
Precedes(check_sensors, move_square);
38
}
O ponto crucial é que tanto o check_sensors e tarefas move_square podem
controlar motores apenas se nenhuma outra tarefa é utilizá-los: isto é feito usando o
Acquire declaração de que espera o moveMutex mútua exclusão variável a ser libertado
antes de utilizar motores. A contrapartida é o comando Adquirir Release comando, que
liberta o mutex variável tão outras tarefas podem usar o recurso crítico, motores, no
nosso caso. O código dentro do acquirerelease âmbito de aplicação é chamado crítico
região: crítica compartilhada significa que os recursos são utilizados. Desta forma
tarefas não pode interferem uns com os outros.
Usando Semáforos
Existe uma alternativa à mão-fabricados mutex variáveis que é explícita a
aplicação da aquisição e Lançamento comandos. Uma norma técnica para resolver este
problema é utilizar uma variável para indicar qual a tarefa é o controle dos motores. As
outras tarefas não estão autorizados a conduzir os motores até que a primeira tarefa
indica, utilizando a variável, que é pronto. Essa variável é freqüentemente chamado um
semáforo. Deixa sem ser essa uma semáforo (o mesmo que mutex). Assumimos que um
valor de 0 indica que nenhuma tarefa é governar o motor (recurso é gratuito). Agora,
sempre que uma tarefa quer fazer algo com os motores que executa os seguintes
comandos:
until (sem == 0);
sem = 1; //Acquire(sem);
// Do something with the motors
// critical region
sem = 0; //Release(sem);
Por isso, primeiro ninguém precisa esperar até os motores. Então, o controlo
através da definição de crédito sem a 1. Agora, pode controlar os motores. Quando
estamos a fazer é definir sem volta para 0. Aqui você encontra o programa anterior,
implementada através de um semáforo. Quando o sensor toque toca alguma coisa, o
semáforo está definido e é o procedimento de backup realizada. Durante este processo, a
tarefa move_square deve esperar. Neste momento, o back-up está pronta, o semáforo
está definido para 0 e move_square pode continuar.
int sem;
task move_square()
{
while (true)
{
until (sem == 0); sem = 1;
OnFwd(OUT_AC, 75);
sem = 0;
Wait(1000);
until (sem == 0); sem = 1;
OnRev(OUT_C, 75);
sem = 0;
Wait(850);
}
}
task submain()
{
SetSensor(IN_1, SENSOR_TOUCH);
while (true)
{
if (SENSOR_1 == 1)
{
until (sem == 0); sem = 1;
OnRev(OUT_AC, 75); Wait(500);
OnFwd(OUT_A, 75); Wait(850);
sem = 0;
}
39
}
}
task main()
{
sem = 0;
Precedes(move_square, submain);
}
Você poderia argumentar que não é necessário em move_square para definir
o semáforo para 1 e de volta para 0. Ainda esta é útil. A razão é que o OnFwd ()
comando é, na realidade, dois comandos (ver capítulo VIII). Você não quer este
comando seqüência deve ser interrompida pela outra tarefa.
Semáforos são muito úteis e, quando está a escrever programas com
paralelo tarefas complicadas, eles são quase sempre exigida. (Há ainda uma pequena
chance que pode falhar. Tentar descobrir porquê.)
Resumo
Neste capítulo, estudamos alguns dos problemas que podem ocorrer quando
você usa diferentes tarefas. Ser sempre muito cuidado para efeitos secundários. Muito
inesperado comportamento é devido a isso. Vimos duas maneiras diferentes de resolver
tais problemas. A primeira solução pára e reinicia tarefas para se certificar de que
apenas uma tarefa crítica estiver sendo executado em todos os momento. A segunda
abordagem utiliza Semáforos para controlar a execução das tarefas. Isso garante que, em
cada momento, apenas a parte crítica de uma tarefa é executada.
11. A comunicação entre robôs
Se você possui mais de um NXT este capítulo é para você (mas você pode
ainda comunicar os dados para o PC, com uma única NXT). Robôs podem se comunicar
uns com os outros via rádio Bluetooth tecnologia: você pode ter várias robôs colaborar
(ou lutar uns com os outros), e você pode construir um robô usando dois grandes
complexos NXTs, de modo que você pode utilizar seis motores e oito sensores.
Para o bom velho RCX, é simples: ele envia uma mensagem e todos os
robôs infravermelho próximo de recebê-la.
Para NXT é toda uma outra coisa! Primeiro, você deve ligar duas ou mais
NXTs (ou NXT para PC), com a onbrick menu Bluetooth e só então você poderá enviar
mensagens para os dispositivos ligados.
O NXT que inicia a conexão é chamado de mestre, e pode ter até 3 Escravo
dispositivos conectados em linhas 1,2,3; Escravos sempre ver o Mestre conectado na
linha 0. Você pode enviar mensagens para 10 caixas disponíveis.
Mestre - Escravo mensagens
Dois programas serão mostrados, um para o comandante, um para o
escravo. Estes programas básicos irá ensinar-lhe como um rápido fluxo contínuo de
corda mensagens podem ser geridas por um dois-NXT rede wireless.
O capitão programa primeiro verifica se o slave está corretamente conectado
na linha 1 (BT_CONN constante), utilizando BluetoothStatus(conn) função; depois
constrói e envia mensagens com um prefixo M e um número crescente com
SendRemoteString(conn,queue,string), enquanto recebe mensagens de escravos com
ReceiveRemoteString(queue,clear,string) e apresenta dados.
40
//MASTER
#define BT_CONN 1
#define INBOX 1
#define OUTBOX 5
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)
{
TextOut(5,LCD_LINE2,"Error");
Wait(1000);
Stop(true);
}
}
task main()
{
string in, out, iStr;
int i = 0;
BTCheck(BT_CONN); //check slave connection
while(true)
{
iStr = NumToStr(i);
out = StrCat("M",iStr);
TextOut(10,LCD_LINE1,"Master Test");
TextOut(0,LCD_LINE2,"IN:");
TextOut(0,LCD_LINE4,"OUT:");
ReceiveRemoteString(INBOX, true, in);
SendRemoteString(BT_CONN,OUTBOX,out);
TextOut(10,LCD_LINE3,in);
TextOut(10,LCD_LINE5,out);
Wait(100);
i++;
}
}
O escravo programa é muito semelhante, mas utiliza SendResponseString
(fila, corda) em vez de SendRemoteString porque escravo devem pode enviar
mensagens apenas para o seu comandante, visto on-line 0.
//SLAVE
#define BT_CONN 1
#define INBOX 5
#define OUTBOX 1
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)
{
TextOut(5,LCD_LINE2,"Error");
Wait(1000);
Stop(true);
}
}
task main()
{
string in, out, iStr;
int i = 0;
BTCheck(0); //check master connection
while(true)
{
iStr = NumToStr(i);
out = StrCat("S",iStr);
TextOut(10,LCD_LINE1,"Slave Test");
TextOut(0,LCD_LINE2,"IN:");
TextOut(0,LCD_LINE4,"OUT:");
ReceiveRemoteString(INBOX, true, in);
SendResponseString(OUTBOX,out);
TextOut(10,LCD_LINE3,in);
TextOut(10,LCD_LINE5,out);
Wait(100);
i++;
}
}
41
Você irá notar que abortar um dos programas, os outros vão continuar a
enviar mensagens com crescente números, sem saber que todas as mensagens enviadas
serão perdidas, porque ninguém está a ouvir o outro lado. Para evitar esse problema,
podemos programar um protocolo mais finas, com aviso de entrega.
Enviando números com aviso
Aqui vemos um outro par de programas: desta vez com o mestre envia
números SendRemoteNumber (conn, fila, número) e parar de esperar por escravos ack
(até ciclo, no qual estamos encontrar ReceiveRemoteString); slave apenas se está a
ouvir e enviar ACKS, prossegue o mestre enviar o próximo mensagem. Escravo
simplesmente recebe número com ReceiveRemoteNumber (fila, claro, o número) e
envia o ack com SendResponseNumber. Seu mestre-escravo programas devem
concordar sobre o Código Comum para a ack, neste caso, eu escolho a hex valor 0xFF.
O mestre envia números aleatórios e aguarda por escravos ack; toda vez que
receber um ack com o código correto, o ack variável deve ser apagada, caso contrário, o
capitão vai continuar enviando sem novos ACKS, porque a variável tenho sujo.
O escravo verifica continuamente a caixa de correio e, se não for vazio,
exibe o valor lido e envia um ack para o mestre. No início do programa, eu optar por
enviar um ack sem ler as mensagens para desbloquear o master; de facto, sem este
artifício, se o capitão para o programa é iniciado primeiro, ele iria enforcar mesmo
começamos escravo posterior. Desta forma as primeiras mensagens se perdem, mas
você pode começar master e slave programas em diferentes momentos sem o risco de
enforcamento.
//MASTER
#define BT_CONN 1
#define OUTBOX 5
#define INBOX 1
#define CLEARLINE(L) 
TextOut(0,L," ");
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)
{
TextOut(5,LCD_LINE2,"Error");
Wait(1000);
Stop(true);
}
}
task main()
{
int ack;
int i;
BTCheck(BT_CONN);
TextOut(10,LCD_LINE1,"Master sending");
while(true)
{
i = Random(512);
CLEARLINE(LCD_LINE3);
NumOut(5,LCD_LINE3,i);
ack = 0;
SendRemoteNumber(BT_CONN,OUTBOX,i);
until(ack==0xFF)
{
until(ReceiveRemoteNumber(INBOX,true,ack)== NO_ERR);
}
Wait(250);
}
}
42
//SLAVE
#define BT_CONN 1
#define OUT_MBOX 1
#define IN_MBOX 5
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)
{
TextOut(5,LCD_LINE2,"Error");
Wait(1000);
Stop(true);
}
}
task main()
{
int in;
BTCheck(0);
TextOut(5,LCD_LINE1,"Slave receiving");
SendResponseNumber(OUT_MBOX,0xFF); //unblock master
while(true)
{
if (ReceiveRemoteNumber(IN_MBOX,true,in)!=
STAT_MSG_EMPTY_MAILBOX)
{
TextOut(0,LCD_LINE3," ");
NumOut(5,LCD_LINE3,in);
SendResponseNumber(OUT_MBOX,0xFF);
}
Wait(10); //take breath (optional)
}
}
Diretório comandos
Há ainda uma outra característica arrefecer sobre comunicação Bluetooth:
mestre pode controlar diretamente seus escravos.
No próximo exemplo, o mestre envia ao escravo directo comandos para
reproduzir sons e mover um automóvel, não há necessidade de um programa escravo,
uma vez que é o firmware do NXT escravo para receber e gerenciar mensagens!
//MASTER
#define BT_CONN 1
#define MOTOR(p,s) RemoteSetOutputState(BT_CONN, p, s, 
OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED, 
OUT_REGMODE_SPEED, 0, OUT_RUNSTATE_RUNNING, 0)
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)
{
TextOut(5,LCD_LINE2,"Error");
Wait(1000);
Stop(true);
}
}
task main()
{
BTCheck(BT_CONN);
RemotePlayTone(BT_CONN, 4000, 100);
until(BluetoothStatus(BT_CONN)==NO_ERR);
Wait(110);
RemotePlaySoundFile(BT_CONN, "! Click.rso", false);
until(BluetoothStatus(BT_CONN)==NO_ERR);
//Wait(500);
RemoteResetMotorPosition(BT_CONN,OUT_A,true);
until(BluetoothStatus(BT_CONN)==NO_ERR);
MOTOR(OUT_A,100);
Wait(1000);
MOTOR(OUT_A,0);
43
}
Resumo
Neste capítulo, estudamos alguns dos aspectos básicos da comunicação
Bluetooth entre robôs: conectando dois NXTs, enviar e receber textos, números e à
espera de entrega ackowledgments. Este último aspecto é muito importante quando um
protocolo de comunicação seguro é necessário.
Como característica adicional, você também aprendeu como enviar
comandos para um escravo directo tijolo.
XII. Mais comandos
NXC tem uma série de comandos adicionais. Neste capítulo vamos discutir três
tipos: a utilização do temporizador, Comandos para controlar a exibição, e da utilização de
sistema de arquivos NXT.
Tempo
O NXT tem um temporizador que é executado continuamente. Este
temporizador carrapatos em incrementos de 1 / 1000 de um segundo. Você pode obter
o valor atual do temporizador com CurrentTick(). Aqui está um exemplo do uso de um
temporizador. As seguintes programa permite que o robô tipo de unidade aleatória
durante 10 segundos.
task main()
{
long t0, time;
t0 = CurrentTick();
do
{
time = CurrentTick()-t0;
OnFwd(OUT_AC, 75);
Wait(Random(1000));
OnRev(OUT_C, 75);
Wait(Random(1000));
}
while (time<10000);
Off(OUT_AC);
}
Você pode querer comparar o programa com a uma dada no capítulo IV,
que fez exatamente a mesma tarefa. O um com temporizadores é definitivamente mais
simples.
Timers são muito úteis como um substituto para um Wait()comando. Você
pode dormir durante um determinado período de tempo ao redefinir um temporizador e
espera, em seguida, até que ele chegue a um determinado valor. Mas você também pode
reagir em outros eventos (por exemplo, de sensores), enquanto espera. O seguinte
programa simples é um exemplo disto. Isso permite que o robô unidade até ou 10
segundos são passado, ou o toque sensor toca alguma coisa.
task main()
{
long t3;
SetSensor(IN_1,SENSOR_TOUCH);
t3 = CurrentTick();
44
OnFwd(OUT_AC, 75);
until ((SENSOR_1 == 1) || ((CurrentTick()-t3) > 10000));
Off(OUT_AC);
}
Não se esqueça que temporizadores trabalho em carrapatos de 1 / 1000 de
um segundo, tal como o comando esperar.
Matricial visor
NXT características um tijolo preto e branco matricial ecrã com uma
resolução de 100x64 pixels. Existem muitas API funções para desenhar texto strings,
números, pontos, linhas, retângulos, círculos, e até mesmo imagens bitmap (. ric
arquivos). O próximo exemplo tenta abranger todos estes casos. Pixel numeradas (0,0) é
um canto inferior esquerdo.
#define X_MAX 99
#define Y_MAX 63
#define X_MID (X_MAX+1)/2
#define Y_MID (Y_MAX+1)/2
task main()
{
int i = 1234;
TextOut(15,LCD_LINE1,"Display", true);
NumOut(60,LCD_LINE1, i);
PointOut(1,Y_MAX-1);
PointOut(X_MAX-1,Y_MAX-1);
PointOut(1,1);
PointOut(X_MAX-1,1);
Wait(200);
RectOut(5,5,90,50);
Wait(200);
LineOut(5,5,95,55);
Wait(200);
LineOut(5,55,95,5);
Wait(200);
CircleOut(X_MID,Y_MID-2,20);
Wait(800);
ClearScreen();
GraphicOut(30,10,"faceclosed.ric"); Wait(500);
ClearScreen();
GraphicOut(30,10,"faceopen.ric");
Wait(1000);
}
Todas estas funções são bastante auto-explicativo, mas agora eu vou
descrever em detalhe os seus parâmetros.
ClearScreen() limpa a tela;
NumOut(x, y, number) permite que você especifique coordenadas, e número;
TextOut(x, y, string) trabalha como acima, mas saídas uma cadeia de texto
GraphicOut(x, y, filename) mostra um bitmap. Ric arquivo
CircleOut(x, y, radius) saídas de um círculo determinado pelas coordenadas do centro e
raio;
LineOut(x1, y1, x2, y2) desenha uma linha que vai do ponto (x1, x2) a (x2, y2)
PointOut(x, y) coloca um ponto na tela
RectOut(x, y, width, height) desenha um retângulo com o vértice no canto inferior
esquerdo (x, y) e com o dimensões especificadas;
ResetScreen() redefine o ecrã.
File system
O NXT pode escrever e ler arquivos, armazenados no seu memória flash.
Então, você poderia salvar um datalog dados de sensores números ou ler durante o
45
programa execução. O único limite no número e dimensão arquivos é o tamanho do
flash
memória. NXT funções API permitem-lhe gerir ficheiros (criar, renomear, excluir,
localizar), permitem-lhe ler e escrever texto strings, números e único bytes.
No próximo exemplo, iremos ver como criar um arquivo, gravar nele cordas
e renomeá-lo.
Primeiro, o programa elimina arquivos com nomes vamos usar: não é um
bom hábito (devíamos verificar para o arquivo existência, excluí-lo manualmente ou
automaticamente escolher outro nome para o nosso trabalho arquivo), mas não há
problema em nosso caso simples. Ela cria o nosso arquivo de CreateFile("Danny.txt",
512, fileHandle), especificando o nome, dimensão e um identificador para o arquivo,
onde NXT firmware irá escrever um número para seu próprio uso.
Então ele constrói cordas e escrever no arquivo com transporte regresso com
WriteLnString(fileHandle,string,bytesWritten), onde todos os parâmetros devem ser
variáveis. Finalmente, o processo é encerrado e renomeado. Lembre-se: um arquivo
deve ser fechado antes de iniciar outra operação, por isso, se você criou um arquivo que
você pode escrever para ele; se você quiser ler a partir dele, você deve fechá-lo e abri-lo
com OpenFileRead()para apagar / renomeá-lo, você deve fechá-la.
#define OK LDR_SUCCESS
task main()
{
byte fileHandle;
short fileSize;
short bytesWritten;
string read;
string write;
DeleteFile("Danny.txt");
DeleteFile("DannySays.txt");
CreateFile("Danny.txt", 512, fileHandle);
for(int i=2; i<=10; i++ )
{
write = "NXT is cool ";
string tmp = NumToStr(i);
write = StrCat(write,tmp," times!");
WriteLnString(fileHandle,write, bytesWritten);
}
CloseFile(fileHandle);
RenameFile("Danny.txt","DannySays.txt");
}
NXT Explorer, carregar DannySays.txt para PC e dar uma olhada. Para
ver o resultado, vá para Ferramentas BricxCC Pronto para o próximo exemplo! Vamos
criar uma tabela com os caracteres ASCII.
task main()
{
byte handle;
if (CreateFile("ASCII.txt", 2048, handle) == NO_ERR)
{
for (int i=0; i < 256; i++)
{
string s = NumToStr(i);
int slen = StrLen(s);
WriteBytes(handle, s, slen);
WriteLn(handle, i);
}
CloseFile(handle);
}
}
46
Realmente simples, este programa cria o arquivo e, se não ocorreu nenhum
erro, ele escreve um número de 0 a 255 (convertendo é a seqüência anterior) com
WriteBytes (handle, s, sLen), que é outra maneira de escrever sem cordas carriage
return; então, escreve o número que está com WriteLn (handle, valor), que acrescenta
um retorno de carro. O resultado, que você pode ver como ASCII.txt antes de abrir com
um editor de texto (como o Windows Notepad), é tão explicável: o número escrito como
uma string é mostrada na forma legível por humanos, enquanto que o número escrito
como hex valor é interpretado e apresentado como um código ASCII.
Duas funções importantes continuam a ser revelou: ReadLnString para ler
strings de arquivos e ReadLn a ler números.
Agora para o exemplo para o primeiro: a tarefa principal CreateRandomFile
chamadas subrotinas que gera um arquivo com números aleatórios do mesmo (escritas
como strings); você pode comentar essa linha e usar uma outra mão-criado arquivo
texto para este exemplo.
Em seguida, a tarefa principal abre o arquivo para leitura, que lê uma linha
de uma só vez até ao final do arquivo, chamando ReadLnString função e exibe texto.
No CreateRandomFile subrotina que geram uma quantidade predefinida de
números aleatórios, convertê-los para string e escrevê-los para o arquivo.
O ReadLnString aceita um arquivo manusear e uma variável string como
argumentos: após a chamada, o texto será conter uma linha de texto ea função irá
retornar um código de erro, que pode utilizar para saber se o final do arquivo foi
atingido.
#define FILE_LINES 10
sub CreateRandomFile(string fname, int lines)
{
byte handle;
string s;
int bytesWritten;
DeleteFile(fname);
int fsize = lines*5;
//create file with random data
if(CreateFile(fname, fsize, handle) == NO_ERR)
{
int n;
repeat(FILE_LINES)
{
int n = Random(0xFF);
s = NumToStr(n);
WriteLnString(handle,s,bytesWritten);
}
CloseFile(handle);
}
}
task main()
{
byte handle;
int fsize;
string buf;
bool eof = false;
CreateRandomFile("rand.txt",FILE_LINES);
if(OpenFileRead("rand.txt", fsize, handle) == NO_ERR)
{
TextOut(10,LCD_LINE2,"Filesize:");
NumOut(65,LCD_LINE2,fsize);
Wait(600);
until (eof == true) // read the text file till the end
{
if(ReadLnString(handle,buf) != NO_ERR) eof = true;
ClearScreen();
TextOut(20,LCD_LINE3,buf);
Wait(500);
}
47
}
CloseFile(handle);
}
No último programa, vou mostrar-lhe como ler números a partir de um
arquivo.
Aproveito a ocasião para vos dar uma pequena amostra de compilação condicional. No
iníciodo código, existe um definição que não seja utilizado para uma macro nem para
um alias: nós simplesmente definir INT.
Depois, há uma declaração preprocessador
#ifdef INT
…Code…
#endif
que simplesmente diz ao compilador para compilar o código entre as duas
afirmações se INT como foi previamente definido. Então, se nós definimos INT, a tarefa
principal no interior do primeiro casal será compilado e se LONGO é definido, em vez
de
INT, a segunda versão do principal será compilado.
Este método permite-me mostrar em um único programa tanto como int (16
bits) e longo (32 bits) tipos podem ser lidos a partir do arquivo chamando a mesma
função ReadLn (handle, val).
Tal como antes, ele aceita um arquivo punho e uma variável numérica como
argumentos, retornando um código de erro.
A função irá ler 2 bytes do arquivo, se passou a variável é declarada como
int, e vai ler 4 bytes se o variável é longo. Bool variáveis também podem ser escritos e
lidos da mesma forma.
#define INT // INT or LONG
#ifdef INT
task main ()
{
byte handle, time = 0;
int n, fsize,len, i;
int in;
DeleteFile("int.txt");
CreateFile("int.txt",4096,handle);
for (int i = 1000; i<=10000; i+=1000)
{
WriteLn(handle,i);
}
CloseFile(handle);
OpenFileRead("int.txt",fsize,handle);
until (ReadLn(handle,in)!=NO_ERR)
{
ClearScreen();
NumOut(30,LCD_LINE5,in);
Wait(500);
}
CloseFile(handle);
}
#endif
#ifdef LONG
task main ()
{
byte handle, time = 0;
int n, fsize,len, i;
long in;
DeleteFile("long.txt");
CreateFile("long.txt",4096,handle);
for (long i = 100000; i<=1000000; i+=50000)
{
WriteLn(handle,i);
48
}
CloseFile(handle);
OpenFileRead("long.txt",fsize,handle);
until (ReadLn(handle,in)!=NO_ERR)
{
ClearScreen();
NumOut(30,LCD_LINE5,in);
Wait(500);
}
CloseFile(handle);
}
#endif
Resumo
Neste último capítulo que preenchidas as avançadas funcionalidades
oferecidas pela NXT: alta resolução timer, matricial e visor filesystem.
13. Observações finais
Se você trabalhou o seu caminho através deste tutorial você pode agora
considerar bastante especialista em NXC. Se não tiver feito isso, até agora, é tempo para
começar a experimentar sozinho. Com criatividade em design e programação você pode
tornar robôs Lego fazer coisas inacreditáveis. Este tutorial não cobrem todos os aspectos
da BricxCC. Está recomendado a leitura do Guia NXC em cada capítulo. Além disso,
NXC ainda está em desenvolvimento, a versão futura poderia incorporar funcionalidade
adicional. Muitos conceitos de programação, não foram tratados neste tutorial. Em
particular, nós não consideramos comportamento de aprendizagem robôs ou outros
aspectos da inteligência artificial. Também é possível conduzir um robô Lego
diretamente de um PC. Isto requer que você para escrever um programa em uma
linguagem como C + +, Visual Basic, Java ou Delphi. Também é possível deixar que
um tal programa trabalhará em conjunto com um NXC programa em execução no NXT
si. Essa combinação é muito poderoso. Se você estiver interessado nesta forma de
programação do seu robot, melhor começar com o download do SDK Fantom e Open
Source documentos da NXTreme secção de Lego Mindstorms site.
http://mindstorms.lego.com/Overview/NXTreme.aspx
A web é uma fonte perfeita para informações adicionais. Alguns outros
pontos importantes são sobre LUGNET, a LEGO Users Group Network (não oficial):
http://www.lugnet.com/robotics/nxt

Mais conteúdo relacionado

Destaque

Guia de aprendizaje 4 cms
Guia de aprendizaje 4 cmsGuia de aprendizaje 4 cms
Guia de aprendizaje 4 cmslechonahp
 
Monografia Glaycon análise cinemática da natação de iniciantes
Monografia Glaycon análise cinemática da natação de iniciantesMonografia Glaycon análise cinemática da natação de iniciantes
Monografia Glaycon análise cinemática da natação de iniciantesMário Campos
 
Memorial.descritivo industrial
Memorial.descritivo industrialMemorial.descritivo industrial
Memorial.descritivo industrialfabiohsouzafhs
 
11_SH를 이용한 실시간 투명 근사법
11_SH를 이용한 실시간 투명 근사법11_SH를 이용한 실시간 투명 근사법
11_SH를 이용한 실시간 투명 근사법noerror
 
Gestión de contenidos
Gestión de contenidosGestión de contenidos
Gestión de contenidosguss1996
 
De Reis van de Heldin Creatief van een Andere Orde
De Reis van de Heldin Creatief van een Andere Orde De Reis van de Heldin Creatief van een Andere Orde
De Reis van de Heldin Creatief van een Andere Orde Peter de Kuster
 
Introducción.pptx_
  Introducción.pptx_  Introducción.pptx_
Introducción.pptx_Maaria Cruxx
 
Transformation_in_Business
Transformation_in_BusinessTransformation_in_Business
Transformation_in_BusinessFrank Edelkraut
 
Abvcap guia pevc_out2013_v5
Abvcap guia pevc_out2013_v5Abvcap guia pevc_out2013_v5
Abvcap guia pevc_out2013_v5Manuel Fernandes
 
Em discussão! agosto 2011_internet
Em discussão! agosto 2011_internetEm discussão! agosto 2011_internet
Em discussão! agosto 2011_internetrcatanese
 
SISTEMAS OPERATIVOS Presentación grupo 8
SISTEMAS OPERATIVOS Presentación grupo 8SISTEMAS OPERATIVOS Presentación grupo 8
SISTEMAS OPERATIVOS Presentación grupo 8jwruizeche
 
Introducción a las redes locales arley perez
Introducción a las redes locales arley perezIntroducción a las redes locales arley perez
Introducción a las redes locales arley perezArley Mauricio Perez
 
Minería y adaptación
Minería y adaptaciónMinería y adaptación
Minería y adaptaciónOBGEOTAN
 
Leyes basicas para un sistema
Leyes basicas para un sistemaLeyes basicas para un sistema
Leyes basicas para un sistemaaura1502bianco
 
Duke Digital Collections: From Projects to Program
Duke Digital Collections: From Projects to ProgramDuke Digital Collections: From Projects to Program
Duke Digital Collections: From Projects to ProgramJill Vermillion
 
Advanced Marketing Research - Final
Advanced Marketing Research - FinalAdvanced Marketing Research - Final
Advanced Marketing Research - FinalJuliusLim
 
El graznido de las chachalacas 506
El graznido de las chachalacas 506El graznido de las chachalacas 506
El graznido de las chachalacas 506Martin Triana
 

Destaque (20)

Guia de aprendizaje 4 cms
Guia de aprendizaje 4 cmsGuia de aprendizaje 4 cms
Guia de aprendizaje 4 cms
 
Monografia Glaycon análise cinemática da natação de iniciantes
Monografia Glaycon análise cinemática da natação de iniciantesMonografia Glaycon análise cinemática da natação de iniciantes
Monografia Glaycon análise cinemática da natação de iniciantes
 
A meninado vale
A meninado vale A meninado vale
A meninado vale
 
Memorial.descritivo industrial
Memorial.descritivo industrialMemorial.descritivo industrial
Memorial.descritivo industrial
 
11_SH를 이용한 실시간 투명 근사법
11_SH를 이용한 실시간 투명 근사법11_SH를 이용한 실시간 투명 근사법
11_SH를 이용한 실시간 투명 근사법
 
Gestión de contenidos
Gestión de contenidosGestión de contenidos
Gestión de contenidos
 
De Reis van de Heldin Creatief van een Andere Orde
De Reis van de Heldin Creatief van een Andere Orde De Reis van de Heldin Creatief van een Andere Orde
De Reis van de Heldin Creatief van een Andere Orde
 
Introducción.pptx_
  Introducción.pptx_  Introducción.pptx_
Introducción.pptx_
 
Transformation_in_Business
Transformation_in_BusinessTransformation_in_Business
Transformation_in_Business
 
Abvcap guia pevc_out2013_v5
Abvcap guia pevc_out2013_v5Abvcap guia pevc_out2013_v5
Abvcap guia pevc_out2013_v5
 
Em discussão! agosto 2011_internet
Em discussão! agosto 2011_internetEm discussão! agosto 2011_internet
Em discussão! agosto 2011_internet
 
SISTEMAS OPERATIVOS Presentación grupo 8
SISTEMAS OPERATIVOS Presentación grupo 8SISTEMAS OPERATIVOS Presentación grupo 8
SISTEMAS OPERATIVOS Presentación grupo 8
 
Introducción a las redes locales arley perez
Introducción a las redes locales arley perezIntroducción a las redes locales arley perez
Introducción a las redes locales arley perez
 
Trabajo
TrabajoTrabajo
Trabajo
 
A meninado vale-belpesce
A meninado vale-belpesceA meninado vale-belpesce
A meninado vale-belpesce
 
Minería y adaptación
Minería y adaptaciónMinería y adaptación
Minería y adaptación
 
Leyes basicas para un sistema
Leyes basicas para un sistemaLeyes basicas para un sistema
Leyes basicas para un sistema
 
Duke Digital Collections: From Projects to Program
Duke Digital Collections: From Projects to ProgramDuke Digital Collections: From Projects to Program
Duke Digital Collections: From Projects to Program
 
Advanced Marketing Research - Final
Advanced Marketing Research - FinalAdvanced Marketing Research - Final
Advanced Marketing Research - Final
 
El graznido de las chachalacas 506
El graznido de las chachalacas 506El graznido de las chachalacas 506
El graznido de las chachalacas 506
 

Semelhante a Nxt Bricx

Introdução à Programação com Robôs Lego
Introdução à Programação com Robôs LegoIntrodução à Programação com Robôs Lego
Introdução à Programação com Robôs LegoRayner Pires
 
Conhecendo o sistema operacional ubunt uca
Conhecendo o sistema operacional ubunt ucaConhecendo o sistema operacional ubunt uca
Conhecendo o sistema operacional ubunt ucaIlton Bruno
 
Curso python
Curso pythonCurso python
Curso pythonTiago
 
Aula de C para Linux
Aula de C para LinuxAula de C para Linux
Aula de C para LinuxChris x-MS
 
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...Fernando Macedo
 
Kinect e Natural Users Interfaces
Kinect e Natural Users InterfacesKinect e Natural Users Interfaces
Kinect e Natural Users InterfacesMauricio Alegretti
 
Visualg 1231617089791929-2
Visualg 1231617089791929-2Visualg 1231617089791929-2
Visualg 1231617089791929-2jaoozinhoqi123
 
Apostiladepic basic-110602153048-phpapp02
Apostiladepic basic-110602153048-phpapp02Apostiladepic basic-110602153048-phpapp02
Apostiladepic basic-110602153048-phpapp02Yury Pontes
 
Curso python
Curso pythonCurso python
Curso pythonTiago
 
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)Fernando Passold
 
Assembly para pc-25paginas
Assembly para pc-25paginasAssembly para pc-25paginas
Assembly para pc-25paginasMikeNandes
 

Semelhante a Nxt Bricx (20)

Introdução à Programação com Robôs Lego
Introdução à Programação com Robôs LegoIntrodução à Programação com Robôs Lego
Introdução à Programação com Robôs Lego
 
Conhecendo o sistema operacional ubunt uca
Conhecendo o sistema operacional ubunt ucaConhecendo o sistema operacional ubunt uca
Conhecendo o sistema operacional ubunt uca
 
Guia xna
Guia xnaGuia xna
Guia xna
 
Curso python
Curso pythonCurso python
Curso python
 
Aula de C para Linux
Aula de C para LinuxAula de C para Linux
Aula de C para Linux
 
Manual dev c
Manual dev cManual dev c
Manual dev c
 
Manual Dev C++
Manual Dev C++Manual Dev C++
Manual Dev C++
 
Robótica - Lego
Robótica - LegoRobótica - Lego
Robótica - Lego
 
Apostila programacao
Apostila programacaoApostila programacao
Apostila programacao
 
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...
Apostila tre.rs2014 direito_eleitoral_pedrokuhnApostila tre.rs2014 informatic...
 
Kinect e Natural Users Interfaces
Kinect e Natural Users InterfacesKinect e Natural Users Interfaces
Kinect e Natural Users Interfaces
 
Visualg 1231617089791929-2
Visualg 1231617089791929-2Visualg 1231617089791929-2
Visualg 1231617089791929-2
 
Visualg
VisualgVisualg
Visualg
 
Apple mac-osx
Apple mac-osxApple mac-osx
Apple mac-osx
 
Apostiladepic basic-110602153048-phpapp02
Apostiladepic basic-110602153048-phpapp02Apostiladepic basic-110602153048-phpapp02
Apostiladepic basic-110602153048-phpapp02
 
Apostila de pic basic
Apostila de pic basicApostila de pic basic
Apostila de pic basic
 
Curso python
Curso pythonCurso python
Curso python
 
Apostila s7
Apostila s7Apostila s7
Apostila s7
 
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)
Programação de Kits Lego NXT usando Linguagem Gráfica Nativa (ou NXT-G)
 
Assembly para pc-25paginas
Assembly para pc-25paginasAssembly para pc-25paginas
Assembly para pc-25paginas
 

Mais de Diego Paniago

Mais de Diego Paniago (7)

X Da Questão
X Da QuestãoX Da Questão
X Da Questão
 
Orientação em c++
Orientação em c++Orientação em c++
Orientação em c++
 
Matlab1
Matlab1Matlab1
Matlab1
 
Knuth
KnuthKnuth
Knuth
 
Css basico
Css basicoCss basico
Css basico
 
Calculo numérico
Calculo numéricoCalculo numérico
Calculo numérico
 
Nxt Bricx
 Nxt Bricx Nxt Bricx
Nxt Bricx
 

Último

Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...LuizHenriquedeAlmeid6
 
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024Sandra Pratas
 
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...Martin M Flynn
 
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASQUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASEdinardo Aguiar
 
FCEE - Diretrizes - Autismo.pdf para imprimir
FCEE - Diretrizes - Autismo.pdf para imprimirFCEE - Diretrizes - Autismo.pdf para imprimir
FCEE - Diretrizes - Autismo.pdf para imprimirIedaGoethe
 
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptx
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptxApostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptx
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptxIsabelaRafael2
 
PPT _ Módulo 3_Direito Comercial_2023_2024.pdf
PPT _ Módulo 3_Direito Comercial_2023_2024.pdfPPT _ Módulo 3_Direito Comercial_2023_2024.pdf
PPT _ Módulo 3_Direito Comercial_2023_2024.pdfAnaGonalves804156
 
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 anoAdelmaTorres2
 
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdf
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdfBRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdf
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdfHenrique Pontes
 
Prática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISPrática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISVitor Vieira Vasconcelos
 
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbv19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbyasminlarissa371
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxIsabellaGomes58
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveaulasgege
 
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
Geometria  5to Educacion Primaria EDU  Ccesa007.pdfGeometria  5to Educacion Primaria EDU  Ccesa007.pdf
Geometria 5to Educacion Primaria EDU Ccesa007.pdfDemetrio Ccesa Rayme
 
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024Sandra Pratas
 
Mesoamérica.Astecas,inca,maias , olmecas
Mesoamérica.Astecas,inca,maias , olmecasMesoamérica.Astecas,inca,maias , olmecas
Mesoamérica.Astecas,inca,maias , olmecasRicardo Diniz campos
 
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino FundamentalCartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamentalgeone480617
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOBiatrizGomes1
 
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdfHABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdfdio7ff
 
PLANEJAMENTO anual do 3ANO fundamental 1 MG.pdf
PLANEJAMENTO anual do  3ANO fundamental 1 MG.pdfPLANEJAMENTO anual do  3ANO fundamental 1 MG.pdf
PLANEJAMENTO anual do 3ANO fundamental 1 MG.pdfProfGleide
 

Último (20)

Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
 
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
 
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
 
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASQUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
 
FCEE - Diretrizes - Autismo.pdf para imprimir
FCEE - Diretrizes - Autismo.pdf para imprimirFCEE - Diretrizes - Autismo.pdf para imprimir
FCEE - Diretrizes - Autismo.pdf para imprimir
 
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptx
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptxApostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptx
Apostila da CONQUISTA_ para o 6ANO_LP_UNI1.pptx
 
PPT _ Módulo 3_Direito Comercial_2023_2024.pdf
PPT _ Módulo 3_Direito Comercial_2023_2024.pdfPPT _ Módulo 3_Direito Comercial_2023_2024.pdf
PPT _ Módulo 3_Direito Comercial_2023_2024.pdf
 
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
 
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdf
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdfBRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdf
BRASIL - DOMÍNIOS MORFOCLIMÁTICOS - Fund 2.pdf
 
Prática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISPrática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGIS
 
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbv19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
v19n2s3a25.pdfgcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
 
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
Geometria  5to Educacion Primaria EDU  Ccesa007.pdfGeometria  5to Educacion Primaria EDU  Ccesa007.pdf
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
 
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
 
Mesoamérica.Astecas,inca,maias , olmecas
Mesoamérica.Astecas,inca,maias , olmecasMesoamérica.Astecas,inca,maias , olmecas
Mesoamérica.Astecas,inca,maias , olmecas
 
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino FundamentalCartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
 
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdfHABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
 
PLANEJAMENTO anual do 3ANO fundamental 1 MG.pdf
PLANEJAMENTO anual do  3ANO fundamental 1 MG.pdfPLANEJAMENTO anual do  3ANO fundamental 1 MG.pdf
PLANEJAMENTO anual do 3ANO fundamental 1 MG.pdf
 

Nxt Bricx

  • 1. 1 Programando Robôs NXT Usando NXC (Beta 30 or higher) (Version 2.2, June 7, 2007) Por Daniele Benedettelli Com Revisões de John Hansen
  • 2. 2 Prefácio Tal como aconteceu para o bom e velho Mindstorms RIS, CyberMaster, e Spybotics, para libertar todo o potencial das Mindstorms NXT tijolo, você precisa de um ambiente de programação que é mais útil do que NXT-G, o Nacional Instrumentos LabView-como linguagem gráfica que vem com NXT retalho set. NXC é uma linguagem de programação, inventado por John Hansen, que foi especialmente concebido para a Lego robôs. Se você nunca escreveu um programa antes, não se preocupe. NXC é realmente fácil de usar e este tutorial vai levá-lo em seus primeiros passos nesse sentido. Para tornar ainda mais fácil escrever programas, existe a Bricx Command Center (BricxCC). Este utilitário permite que você escreva seus programas, para transferi-los para o robô, para iniciar e detê-los, procure NXT memória flash, converter arquivos sonoros para uso com o tijolo, e muito mais. BricxCC funciona quase como um processador de texto, mas com algumas extras. Este tutorial usará BricxCC (versão 3.3.7.16 ou superior), como ambiente de desenvolvimento integrado (IDE). Você pode baixá-lo gratuitamente a partir da web, no endereço http://bricxcc.sourceforge.net/ BricxCC é executado no PC Windows (95, 98, ME, NT, 2K, XP, Vista). NXC A língua também pode ser usado em outras plataformas. Você pode baixá-lo da página web http://bricxcc.sourceforge.net/nxc/ A maior parte deste tutorial deve ser igualmente aplicável a outras plataformas, exceto que você solta algumas das ferramentas incluídas no BricxCC e a cor-codificação. O tutorial foi atualizado para trabalhar com beta 30 de NXC e versões superiores. Alguns programas da amostra não irão compilar com versões mais antigas do que beta 30. Como nota lateral, minha página está cheia de RCX Lego Mindstorms NXT e conteúdo relacionado, incluindo uma ferramenta para PC comunicar com NXT: http://daniele.benedettelli.com Agradecimentos Muitos agradecimentos vão para John Hansen, cujo trabalho não tem preço!
  • 3. 3 Sumário Prefácio ....................................................................................................................................... 2 Agradecimentos .............................................................................................................................2 Sumário........................................................................................................................................ 3 1. Gravando o seu primeiro programa...................................................................................... 5 Construir um robô ..........................................................................................................................5 Começando Bricx Command Center..............................................................................................5 Escrever o programa.......................................................................................................................6 Executando o programa .................................................................................................................7 Erros em seu programa...................................................................................................................8 Mudar a velocidade ........................................................................................................................8 Resumo...........................................................................................................................................9 2. Um programa mais interessante ......................................................................................... 10 Tornar voltas ............................................................................................................................... 10 Repetindo comandos ...................................................................................................................10 Adicionando comentários.............................................................................................................11 Resumo ........................................................................................................................................ 12 3. Usando variáveis ................................................................................................................... 13 Passando em uma espiral..............................................................................................................13 Números aleatórios ......................................................................................................................14 Resumo.........................................................................................................................................15 4. Controle estruturas ............................................................................................................... 16 A declaração IF ...........................................................................................................................16 A declaração do............................................................................................................................17 Resumo ........................................................................................................................................ 17 5. Sensores ..............................................................................................................................................18 Esperando por um sensor ............................................................................................................18 Agindo sobre um sensor de Toque ............................................................................................... 19 Sensor de Luz............................................................................................................................... 19 Sensor de Som .............................................................................................................................20 Sensor de Ultra-som .....................................................................................................................21 Resumo ........................................................................................................................................ 22 6. Tarefas e Sub-Rotinas .....................................................................................................................23 Tarefas .........................................................................................................................................23 Sub-Rotinas .................................................................................................................................24 Definindo macros ........................................................................................................................ 25 Resumo ........................................................................................................................................ 26 7. Fazendo música .................................................................................................................................28 Reproduzir arquivos sonoros ....................................................................................................... 28 Reproduzir música ....................................................................................................................... 28 Resumo ........................................................................................................................................ 30 8. Mais informações sobre os motores .............................................................................................31 Parando suavemente ....................................................................................................................31 Comandos avançados ...................................................................................................................31 Controle PID ............................................................................................................................... 33 Resumo ........................................................................................................................................ 34 9. Mais informações sobre os sensores ............................................................................................35 Sensor modalidade e tipo ............................................................................................................35 A rotação sensor...........................................................................................................................36 Colocar vários sensores em uma entrada .....................................................................................37 Resumo ........................................................................................................................................ 38 10. Tarefas Paralelas ............................................................................................................................39 Um programa errado ...................................................................................................................39 Secções críticas e variáveis mutex ............................................................................................... 39 Usando Semáforos ....................................................................................................................... 40 Resumo ........................................................................................................................................ 41
  • 4. 4 11. A comunicação entre robôs ............................................................................................... 42 Mestre - Escravo mensagens ....................................................................................................... 42 Enviando números com aviso ......................................................................................................43 Diretório de comandos .................................................................................................................45 Resumo ........................................................................................................................................ 45 12. Mais comandos ................................................................................................................... 46 Temporizadores ...........................................................................................................................46 Matricial visor .............................................................................................................................46 Sistema Arquivo...........................................................................................................................47 Resumo ........................................................................................................................................ 50 13. Observações finais .........................................................................................................................51
  • 5. 5 1. Gravando o seu primeiro programa Neste capítulo vou mostrar-lhe como escrever um programa extremamente simples. Estamos indo para programar um robô para avançar para 4 segundos, depois de recuar mais 4 segundos, e então parar. Não muito espetacular, mas irá apresentar-lhe a idéia de base da programação. E ele vai te mostrar como isso é fácil. Mas antes que nós possamos escrever um programa, primeiro precisamos um robô. Construir um robô O robô, utilizado ao longo deste tutorial é Tribot, o primeiro veículo que tenha sido instruído a construir quando tem NXT estabelecidos fora da caixa. A única diferença é que você deve se conectar a porta um motor direita, esquerda automóvel à porta C e do motor para a porta B. Certifique-se de ter instalado corretamente Mindstorms NXT Fantom Drivers que vem com o seu conjunto. Começando Bricx Command Center Nós escrevemos nossos programas usando Bricx Command Center. Iniciá-lo clicando duas vezes sobre o ícone BricxCC. (Eu assumo você já instalou BricxCC. Se não, fazer o download a partir do web site (veja o prefácio), e instalá-lo em qualquer diretório que você gosta. O programa irá pedir a localização do robot. Mudar o robô, e pressione OK. O programa (o mais provável) encontrar automaticamente o robô. Agora a interface do usuário aparece como mostrado abaixo (sem o texto guia).
  • 6. 6 A interface parece um editor de texto padrão, com o habitual menu e botões para abrir e salvar arquivos, impressão arquivos, editar arquivos, etc Mas também existem alguns menus especiais para compilar e baixar programas para o robô e para obter informações a partir do robô. Você pode ignorar estes para o momento. Vamos agora escrever um novo programa. Então, pressione o botão Novo para criar um arquivo novo e vazio janela. Escrever o programa Agora digite o seguinte programa: task main() { OnFwd(OUT_A, 75); OnFwd(OUT_C, 75); Wait(4000); OnRev(OUT_AC, 75); Wait(4000); Off(OUT_AC); } Pode parecer um pouco complicado num primeiro momento, vamos analisá-lo assim. Programas em NXC composto de tarefas. Nosso programa tem apenas uma tarefa, chamado principal. Cada programa deverá ter uma chamada tarefa principal, que é a que vai ser executada pelo robô. Você vai aprender mais sobre a missão no capítulo VI. Uma tarefa consiste de uma série de comandos, também chamados de declarações. Há cerca de parênteses as declarações tal que, é claro que todos eles pertencem a esta tarefa. Cada declaração termina com um ponto e vírgula. Desta forma, é evidente uma declaração onde acaba e onde começa a próxima declaração. Então, parece uma tarefa, em geral, como segue: task main()
  • 7. 7 { statement1; statement2; … } Nosso programa tem seis declarações. Olhemos para um deles no momento: OnFwd(OUT_A, 75); Esta declaração diz o robô para iniciar uma produção, ou seja, o motor ligado à saída marcada Ano NXT, para avançar. O número seguinte apresenta a velocidade do motor a 75% da velocidade máxima. OnFwd(OUT_C, 75); Mesma declaração, mas agora começamos a motor C. Após estas duas declarações, ambos os motores estão funcionando, e os robôs se move em frente. Wait(4000); Agora é tempo para esperar por um tempo. Esta afirmação diz-nos a esperar por 4 segundos.O argumento, isto é, o número entre parênteses, indica o número de 1 / 1000 de um segundo: assim que você pode dizer muito claramente ao programa como tempo para esperar. Para a 4 segundos, o programa está dormindo e o robô continua a avançar. OnRev(OUT_AC, 75); O robô tem agora longe suficiente para dizer que para avançar na direção inversa, ou seja, para trás. Note que nós pode definir ambos os motores de uma vez OUT_AC usando como argumento. Nós também podíamos ter combinado das duas primeiras declarações desta forma. Wait(4000); Novamente vamos esperar por 4 segundos. Off(OUT_AC); E finalmente nós dois motores switch off. Esse é todo o programa. Move-se ambos os motores em frente por 4 segundos, em seguida, para trás, para 4 segundos, e finalmente mudá-las. Você, provavelmente já notou as cores quando a digitação no programa. Eles aparecem automaticamente. As cores e estilos utilizado pelo editor quando se realiza sintaxe highlighting são personalizáveis. Executando o programa Depois de ter escrito um programa, ele precisa ser compilado (ou seja, transformada em código binário que o robô pode compreender e executar) e enviado para o robô usando o cabo USB ou BT dongle (chamados de "descarregar" os programas). Aqui você pode ver o botão que lhe permite (da esquerda para a direita) compilar, faça o download, executar e parar o programa. Pressione o botão e segundo, assumindo que você fez que não há erros na digitação quando o programa, ele será correctamente compilados e baixadas. (Se houver erros em seu programa, você será notificado, ver abaixo.) Agora você pode executar o seu programa. Para isso, vá ao menu Meus Ficheiros OnBrick, Software arquivos, e execute 1_simple programa. Lembre-se: software NXT arquivos em arquivos têm o mesmo nome como fonte NXC arquivo. Além disso, para obter o programa ser executado automaticamente, pode utilizar o atalho CTRL + F5 ou depois de fazer o download do programa que você pode pressionar o botão verde correr. Será que o robot fazer o que você esperava? Se não, verifique fio conexões. Erros em seu programa
  • 8. 8 Ao digitar nos programas, há uma hipótese razoável que você faça alguns erros. Os avisos do compilador erros e relatá-los a você, na parte inferior da janela, como na figura a seguir: Ela seleciona automaticamente o primeiro erro (nós digitado incorretamente o nome do motor). Quando há mais erros, você pode clique sobre as mensagens de erro de ir para elas. Note que muitas vezes erros no início do programa causar outros erros em outros lugares. Então, melhor apenas corrigir alguns erros do primeiro e, em seguida, compile o programa novamente. Observe também que a sintaxe de ajuda imenso a evitar erros. Por exemplo, na última linha digitada of nós, em vez de Off. Porque este é um comando esconhecido, não é destacada. Existem também erros que não são encontrados pelo compilador. Se tivéssemos digitado OUT_B isto causar o mal motor a girar. Se o seu robô exibe um comportamento inesperado, o mais provável é algo de errado em seu programa. Mudar a velocidade Como você notou, o robô movido bastante rápido. Para alterar a velocidade que você só mudar o segundo parâmetro no interior parênteses. O poder é um número entre 0 e 100. 100 é o mais rápido, 0 significa parar (servo motores irá NXT mantenha posição). Aqui está uma nova versão do nosso programa em que o robô se move lentamente: task main() { OnFwd(OUT_AC, 30); Wait(4000); OnRev(OUT_AC, 30); Wait(4000); Off(OUT_AC); } Resumo
  • 9. 9 Neste capítulo você escreveu seu primeiro programa no NXC, utilizando BricxCC. Agora você deve saber qual o tipo de um programa, como transferir-lo para o robô e como deixar o robô executar o programa. BricxCC pode fazer muitas mais coisas. Para saber mais sobre eles, leia a documentação que vem com ele. Este tutorial irá abordar essencialmente com a língua e só NXC mencionar características da BricxCC quando você realmente precisa deles. Você também aprendeu alguns aspectos importantes da língua NXC. Primeiro de tudo, você aprendeu que cada programa tem uma tarefa que a chamada principal é sempre executado pelo robô. Também você aprendeu o básico motor quatro comandos: OnFwd (), OnRev () e off (). Finalmente, você aprendeu sobre a Wait () declaração. 2. Um programa mais interessante
  • 10. 10 O nosso primeiro programa não foi tão incrível. Então, vamos tentar torná-la mais interessante. Faremos isso em uma série de passos, introduzindo alguns aspectos importantes da nossa linguagem de programação NXC. Tornar voltas Você pode fazer seu robô turno, parando ou invertendo a direção de um dos dois motores. Aqui está um exemplo. Digite a sua senha, fazer o download para o seu robô e deixar correr. Deve dirigir um pouco e então faça um grau 90-direita turno. task main() { OnFwd(OUT_AC, 75); Wait(800); OnRev(OUT_C, 75); Wait(360); Off(OUT_AC); } Você pode ter que experimentar alguns ligeiramente diferentes números superiores a 500 na segunda Esperar () comando para fazer um 90 grau turno. Isso depende do tipo de superfície sobre a qual o robô executa. Ao invés de mudar isso no programa é mais fácil de usar um nome para este número. Em NXC você pode definir valores constantes conforme mostrado na programa seguinte. #define MOVE_TIME 1000 #define TURN_TIME 360 task main() { OnFwd(OUT_AC, 75); Wait(MOVE_TIME); OnRev(OUT_C, 75); Wait(TURN_TIME); Off(OUT_AC); } As duas primeiras linhas definem duas constantes. Estas podem agora ser utilizados em todo o programa. Definindo constantes é boa por dois motivos: ela torna o programa mais legível, e é mais fácil de alterar os valores. Note que BricxCC dá declarações a definir sua própria cor. Como veremos no capítulo VI, você pode também definir as coisas outros que não constantes. Repetindo comandos Vamos agora tentar escrever um programa que faz com que o robô em uma unidade quadrada. Indo em uma praça significa: condução em frente, virar 90 graus, condução em frente de novo, virar 90 graus, etc Podíamos repetir o referido pedaço de Código quatro vezes, mas isso pode ser feito muito mais fácil com a repeat declaração.
  • 11. 11 #define MOVE_TIME 500 #define TURN_TIME 500 task main() { repeat(4) { OnFwd(OUT_AC, 75); Wait(MOVE_TIME); OnRev(OUT_C, 75); Wait(TURN_TIME); } Off(OUT_AC); } O número dentro da repetição da declaração parênteses indica quantas vezes o seu código dentro parênteses deve ser repetido. Note que, no programa acima, também as declarações travessão. Isso não é necessário, mas torna o programa mais legível. Como um último exemplo, vamos fazer o robô unidade 10 vezes em um quadrado. Aqui está o programa: #define MOVE_TIME 1000 #define TURN_TIME 500 task main() { repeat(10) { repeat(4) { OnFwd(OUT_AC, 75); Wait(MOVE_TIME); OnRev(OUT_C, 75); Wait(TURN_TIME); } } Off(OUT_AC); } Existe agora uma declaração repetir dentro da outra. Chamamos isso de "nested" repetir declaração. Você pode repetir ninho declarações o quanto quiser. Tome um cuidado olhar para os suportes e as indentação utilizada no programa. O tarefa começa no primeiro escalão e termina no último. A primeira repetição declaração começa no segundo escalão e termina na quinta. A repetição aninhada declaração começa no terceiro escalão, e termina na quarta. Como você vê os parênteses sempre vêm em pares, e a peça entre os parênteses que travessão. Adicionando comentários Para tornar o programa ainda mais legível, é bom para acrescentar alguns comentários a ele. Sempre que você colocar / / em um linha, o resto da linha é ignorado e pode ser usado para comentários. Um longo comentário pode ser colocada entre / * e * /. Comentários são destacadas na sintaxe BricxCC. A programação completa pode parecer como se segue: /* 10 SQUARES This program make the robot run 10 squares */
  • 12. 12 #define MOVE_TIME 500 // Time for a straight move #define TURN_TIME 360 // Time for turning 90 degrees task main() { repeat(10) // Make 10 squares { repeat(4) { OnFwd(OUT_AC, 75); Wait(MOVE_TIME); OnRev(OUT_C, 75); Wait(TURN_TIME); } } Off(OUT_AC); // Now turn the motors off } Resumo Neste capítulo você aprendeu a utilização da declaração e repetir o uso de comentário. Também você viu a função aninhados de parênteses e ao uso de indentação. Com tudo o que sabemos até agora você pode fazer o robô mover todos juntamente tipos de caminhos. É um bom exercício para tentar escrever algumas variações dos programas neste capítulo antes continuar com o próximo capítulo. 3. Usando variáveis
  • 13. 13 Variáveis forma um aspecto muito importante de todas as linguagens de programação. As variáveis são locais na memória que pode armazenar um valor. Podemos utilizar esse valor em locais diferentes e podemos mudá-la. Vamos descrever a utilização de variáveis usando um exemplo. Passando em uma espiral Suponhamos que queremos adaptar o programa acima de forma a que o robot movimentações em uma espiral. Isto pode ser alcançado , tirando o sono do que tempo de maior circulação para cada lado direto. Isto é, queremos aumentar o valor de MOVE_TIME cada vez. Mas como podemos fazer isso? MOVE_TIME é uma constante e, portanto, não pode ser alterado. Nós necessitamos de uma variável vez. Variáveis podem ser facilmente definida no NXC. Aqui está a espiral programa. #define TURN_TIME 360 int move_time; // define a variable task main() { move_time = 200; // set the initial value repeat(50) { OnFwd(OUT_AC, 75); Wait(move_time); // use the variable for sleeping OnRev(OUT_C, 75); Wait(TURN_TIME); move_time += 200; // increase the variable } Off(OUT_AC); } O interessante linhas são indicados com os comentários. Em primeiro lugar, definir uma variável, digitando a palavra-chave int seguido por um nome que escolhemos. (Normalmente usamos minúscula letras para a variável nomes e letras maiúsculas para constantes, mas isso não é necessário). O nome deve iniciar com uma letra, mas pode conter os dígitos e sublinhado assinar. Não são permitidos outros símbolos. (O mesmo se aplicava aos constantes, tarefa nomes, etc) A palavra está para o int inteiro. Apenas números inteiros podem ser armazenados na mesma. Na segunda linha vamos atribuir o valor 200 para a variável. A partir deste momento em diante, sempre que você usar a variável, o seu valor será 200. Agora segue a repetir em loop que usamos a variável para indicar a hora de dormir e, no final do ciclo que aumentar o valor da variável por 200. Então, a primeira vez que o robô dorme 200 ms, 400 ms, o segundo tempo, o terceiro time 600 ms, e assim ligado. Além de acrescentar valor a uma variável que também pode multiplicar uma variável com um número usando *=, subtrair usando -= e dividir usando / =. (Note que, para a divisão do resultado é arredondado para o número inteiro mais próximo.) Você também pode adicionar uma variável para o outro, e anote mais complicado expressões. O próximo exemplo, não têm qualquer efeito em seu robô de hardware, uma vez que não sabemos como usar o visor NXT ainda! int aaa; int bbb,ccc; int values[];
  • 14. 14 task main() { aaa = 10; bbb = 20 * 5; ccc = bbb; ccc /= aaa; ccc -= 5; aaa = 10 * (ccc + 3); // aaa is now equal to 80 ArrayInit(values, 0, 10); // allocate 10 elements = 0 values[0] = aaa; values[1] = bbb; values[2] = aaa*bbb; values[3] = ccc; } Nota sobre as primeiras duas linhas que podemos definir múltiplas variáveis em uma linha. Nós também podíamos ter combinado tudo três deles em uma linha. A variável denominada valores é uma matriz, ou seja, uma variável que contém mais de um Número: um array pode ser indexada com um número dentro de colchetes. Em NXC inteiro matrizes são declaradas assim: int name[]; Então, esta linha aloca 10 elementos initializing eles a 0. ArrayInit(values, 0, 10); Números aleatórios Em todos os programas acima, definimos exatamente o que o robô era suposto fazer. Mas as coisas se tornam muito mais interessante quando o robô vai fazer coisas que não sabemos. Queremos que haja alguma aleatoriedade na moções. Em NXC você pode criar números aleatórios. O seguinte programa usa isso para deixar a unidade em torno de um robô forma aleatória. É constantemente unidades encaminha para um valor aleatório de tempo e, em seguida, faz uma aleatória turno. int move_time, turn_time; task main() { while(true) { move_time = Random(600); turn_time = Random(400); OnFwd(OUT_AC, 75); Wait(move_time); OnRev(OUT_A, 75); Wait(turn_time); } } O programa define duas variáveis e, em seguida, atribui-lhes números aleatórios. Random(600)significa um aleatória número entre 0 e 600 (o valor máximo não está incluído no intervalo de números devolvida). Cada vez Random chamar os números serão diferentes. Note que pudéssemos evitar o uso das variáveis por escrito directamente por exemplo, Wait(Random(600)). Você também verá um novo tipo de laço aqui. Em vez que a utilização da declaração repetir que escrevemos while (true). O tempo declaração reitera as declarações abaixo dela, enquanto a condição entre parênteses é a verdade. A especial palavra verdadeira é sempre verdadeira, então as declarações entre os parênteses são repetidas indefinidamente (ou, pelo menos até que você pressione o cinzento escuro botão NXT). Você vai aprender mais sobre a declaração enquanto no Capítulo IV.
  • 15. 15 Resumo Neste capítulo você aprendeu sobre o uso de variáveis e matrizes. Você pode declarar do que outros tipos de dados int: short, long, byte, bool e string. Você também aprendeu a criar números aleatórios, de modo que você pode dar o robô um comportamento imprevisível. Finalmente vimos o uso da comunicação a fazer, enquanto um ciclo infinito que vai para sempre. 4. Controle estruturas
  • 16. 16 Nos capítulos anteriores vimos a repetir, e enquanto declarações. Estas declarações controlar a forma como os outros declarações do programa são executados. Eles são chamados de "estruturas de controlo". Neste capítulo veremos alguns outras estruturas de controlo. A declaração IF Às vezes você deseja que uma determinada parte do seu programa só é executado em determinadas situações. Neste caso, o declaração, se for utilizado. Permitam-me dar um exemplo. Vamos mudar novamente o programa que temos vindo a trabalhar com tão longe, mas com um novo giro. Queremos que o robô de condução ao longo de uma linha recta e então fazer a esquerda ou à direita turno. Para isso precisamos de números aleatórios novamente. Nós escolher um número aleatório que é positivo ou negativo. Se o número é inferior a 0 fazemos uma curva à direita, caso fizermos uma esquerda turno. Aqui está o programa: #define MOVE_TIME 500 #define TURN_TIME 360 task main() { while(true) { OnFwd(OUT_AC, 75); Wait(MOVE_TIME); if (Random() >= 0) { OnRev(OUT_C, 75); } else { OnRev(OUT_A, 75); } Wait(TURN_TIME); } } A declaração se parece um pouco como o tempo declaração. Se a condição entre parênteses é a verdade a parte entre os parênteses é executado. Caso contrário, a parte entre os parênteses depois da palavra o resto é executado. Permitir nos olhar um pouco melhor a condição que nós usamos. Ele lê Random() >= 0. Isto significa que Random() deve ser maior que ou igual a 0 para tornar a condição verdadeira. Você pode comparar valores de formas diferentes. Aqui estão os mais importantes: == Igual a < Menor que <= Menor ou igual a > Maior que > = Maior que ou igual a ! = Não igual a Você pode combinar condições usar &&, que significa "e", ou ||,, o que significa "ou". Aqui estão alguns exemplos de condições: true sempre verdade false nunca verdade ttt != 3 verdade quando ttt não é igual a 3 (ttt >= 5) && (ttt <= 10) verdade quando ttt oscila entre 5 e 10 (aaa == 10) || (bbb == 10) verdade se aaa ou bbb forem igual a 10 Note que a declaração se tem duas partes. A parte imediatamente após a condição, que é executado quando o condição é verdadeira, assim como a parte após a outra, que é executada quando a condição é falsa. A palavra-chave e outra a parte depois
  • 17. 17 que são opcionais. Assim, você pode omiti-los, se não há nada a fazer quando a condição é falsa. A declaração do Existe uma outra estrutura de controlo, a fazer declaração. Tem a seguinte forma: do { statements; } while (condition); As declarações entre os parênteses após a fazer parte são executadas enquanto a condição é verdadeira. A condição tem a mesma forma como no caso acima descrito declaração. Aqui está um exemplo de um programa. O robô é executado aleatoriamente em torno de 20 segundos e depois pára. int move_time, turn_time, total_time; task main() { total_time = 0; do { move_time = Random(1000); turn_time = Random(1000); OnFwd(OUT_AC, 75); Wait(move_time); OnRev(OUT_C, 75); Wait(turn_time); total_time += move_time; total_time += turn_time; } while (total_time < 20000); Off(OUT_AC); } Note também que fazer a declaração comporta quase o mesmo que o tempo declaração. Mas enquanto que na declaração do condição é testada antes de executar as declarações, enquanto que nos fazem menção a condição é testada no final. Por enquanto a declaração, as declarações poderiam nunca ser executado, mas para fazer a declaração que são executadas em menos uma vez. Resumo Neste capítulo, vimos duas novas estruturas de controlo: a declaração IF e a declaração DO. Juntamente com o declaração e repetir a declaração enquanto eles são as declarações que controlam a maneira pela qual o programa é executada. É muito importante que você entenda o que eles fazem. Então, melhor tentar mais alguns exemplos yourself antes de continuar. 5. Sensores Claro que você pode se conectar sensores para fazer o robô NXT reagir a eventos externos. Antes que eu posso mostrar como a isso, temos de mudar o robô um
  • 18. 18 pouco, adicionando um toque sensor. Tal como antes, siga as instruções para Tribot construir o pára-choque dianteiro. Ligue o sensor de toque de entrada 1 sobre o NXT. Esperando por um sensor Comecemos com um simples programa no qual o robô drives em frente até que ele acerta algo. Aqui está: task main() { SetSensor(IN_1,SENSOR_TOUCH); OnFwd(OUT_AC, 75); until (SENSOR_1 == 1); Off(OUT_AC); } Existem duas linhas importante aqui. A primeira linha do programa informa ao robô que tipo de sensor que usamos. IN_1 é o número da entrada para que o sensor ligado. O outro sensor insumos são chamados IN_2, IN_3 e IN_4. SENSOR_TOUCH indica que este é um toque sensor. Para o sensor de luz iríamos utilizar SENSOR_LIGHT. Depois de especificar o tipo de sensor, o programa muda de ambos os motores e começa o robô em movimento frente. O próximo mapa é uma construção muito útil. Ele espera até que o estado está entre os parênteses VERDADEIRO. Esta condição indica que o valor do sensor SENSOR_1 deve ser 1, o que significa que o sensor é pressionada. Desde que o sensor não está pressionado, o valor é 0. Portanto, esta declaração aguarda até que o sensor seja pressionado. Então, desligue o motor e para a tarefa está concluída. Agindo sobre um sensor Toque
  • 19. 19 Vamos agora tentar fazer o robô evitar obstáculos. Sempre que o robô atinge um objeto, nós deixá-lo voltar um pouco, fazer uma vez, e em seguida continuar. Aqui está o programa: task main() { SetSensorTouch(IN_1); OnFwd(OUT_AC, 75); while (true) { if (SENSOR_1 == 1) { OnRev(OUT_AC, 75); Wait(300); OnFwd(OUT_A, 75); Wait(300); OnFwd(OUT_AC, 75); } } } Tal como no exemplo anterior, primeiro indicar o tipo de sensor. Em seguida, o robô começa avançar. No loop infinito enquanto estamos constantemente a testar se o sensor é tocado, e, em caso afirmativo, mover de volta para 300 ms, vire à direita para 300 ms, e, em seguida, continuar em frente novamente. Sensor Luz Além de tocar o sensor, você também terá um sensor luz, um som e um sensor digital com sensores ultra-sônicos Mindstorms NXT sistema. O sensor de luz pode ser acionado para emitir luz ou não, assim você pode medir a quantidade de luz refletida ou luz ambiente em uma determinada direção. Medir a luz reflectida é particularmente útil quando tornando um robô seguir uma linha no chão. Isto é o que vamos fazer no próximo exemplo. Para continuar com a experimentos, acabamento Tribot edifício. Conecte sensor de luz de entrada 3, sensor de som de entrada 2 e sensores ultra-sônicos entrada para 4, conforme indicado por instruções. Temos também o teste com o bloco faixa preta que vem com o NXT set. O princípio básico da linha seguinte é que o robô continua a tentar ficar direita, na
  • 20. 20 fronteira com a linha preta, girando fora da linha, se a luz nível é muito baixo (e sensor está no meio da linha) e virando para a linha, se o sensor está fora da faixa e detecta um elevado nível luz. Aqui está um programa muito simples fazer linha seguinte com uma única luz limiar valor. #define THRESHOLD 40 task main() { SetSensorLight(IN_3); OnFwd(OUT_AC, 75); while (true) { if (Sensor(IN_3) > THRESHOLD) { OnRev(OUT_C, 75); Wait(100); until(Sensor(IN_3) <= THRESHOLD); OnFwd(OUT_AC, 75); } } } O programa, primeiro porto 3 configura como uma luz sensor. Em seguida põe- se o robot para avançar e vai para um loop infinito. Sempre que a função valor é maior que 40 (usamos aqui uma constante tal que este pode ser adaptado fácil, porque depende muito do entorno luz) que reverter um motor e aguarde até que estamos no bom caminho novamente. Como você vai ver quando você executar o programa, o movimento não é muito bom. Tente adicionar um Wait(100) comando até antes do comando para fazer o robô mover melhor. Note que o programa não funciona para que se deslocam no sentido anti- horário. Para ativar o movimento ao longo arbitrária um caminho muito mais complicado programa é necessário. Para ler luz ambiente com intensidade levou off, configure o sensor do seguinte modo: SetSensorType(IN_3,IN_TYPE_LIGHT_INACTIVE); SetSensorMode(IN_3,IN_MODE_PCTFULLSCALE); ResetSensor(IN_3); Som sensor Usando o som sensor pode transformar o seu caro NXT fixado em um chocalho! Nós estamos indo para escrever um programa que espera por um som alto, e impulsiona o robô até que outro som é detectado. Fixe o sensor sonoro para a porta 2, conforme descrito no manual Tribot instruções. #define THRESHOLD 40 #define MIC SENSOR_2 task main()
  • 21. 21 { SetSensorSound(IN_2); while(true) { until(MIC > THRESHOLD); OnFwd(OUT_AC, 75); Wait(300); until(MIC > THRESHOLD); Off(OUT_AC); Wait(300); } } Primeiro, definir um THRESHOLD constante e um alias para SENSOR_2; na tarefa principal, que configure a porta 2 do ler dados a partir do som sensor e nós começamos um ciclo para sempre. Usando a declaração até que o programa espera que o nível sonoro a ser superior ao limiar optamos: nota SENSOR_2que não é apenas um nome, mas uma macro que retorna o valor lido som do sensor. Se ocorrer um som alto, o robô começa a ir direto até que outro som pára-lo. A espera declarações foram inseridas, porque caso contrário, o robô seria iniciar e parar imediatamente: na verdade, o NXT é tão rápido que não tem tempo para executar linhas entre os dois até declarações. Se você tentar comentar para fora a primeira ea segunda esperar, você vai entender isso melhor. Uma alternativa para a utilização de até de esperar por eventos é ao mesmo tempo, é suficiente para colocar dentro dos parênteses uma condição complementar, por exemplo, while(MIC <= THRESHOLD). Não há muito mais para saber sobre NXT sensores analógicos, basta lembrar que ambos os sensores luz e som dar-lhe uma leitura de 0 a 100. Sensor ultra-sônico Ultrasonico sensor funciona como um sonar: grosso modo, ele envia um estouro de ondas ultra-sônicas e mede o tempo necessário para as ondas de ser reflectida de volta pelo objeto em vista. Este é um sensor digital, o que significa que tem uma embutido dispositivo integrado para analisar e enviar dados. Com este novo sensor que você pode fazer um robô ver e evitar um obstáculo antes de bater-lo (como é para tocar sensor). #define NEAR 15 //cm task main() { SetSensorLowspeed(IN_4); while(true) { OnFwd(OUT_AC,50); while(SensorUS(IN_4)>NEAR); Off(OUT_AC); OnRev(OUT_C,100); Wait(800); } } O programa inicializa porta 4 para ler dados do sensor digital E.U.; então executa sempre um loop onde vai robôs recta até algo mais perto do que NEAR cm (15 centímetros no nosso exemplo) está em vista, em seguida, backups um pouco e começa frente novamente. Resumo
  • 22. 22 Neste capítulo você viu como trabalhar com todos os sensores incluídos no NXT set. Vimos também until e while comandos são úteis quando se utiliza sensores. Eu recomendo que você escreva um número de programas por si no seu ponto. Você tem todos os ingredientes para dar seus robôs comportamento bastante complicada agora: tentar traduzir em NXC os programas mais simples mostrado na NXT retalho software Robô Centro guia de programação. 6. Tarefas e Sub-Rotinas
  • 23. 23 Até agora todos os nossos programas consistiu de apenas uma tarefa. Mas NXC programas podem ter múltiplas funções. É também possível colocar pedaços de código no âmbito dos chamados sub-rotinas que você pode usar em lugares diferentes em seu programa. Usando funções e sub-rotinas torna os programas mais fáceis de compreender e mais compacta. Neste capítulo, irá analisar as várias possibilidades. Tarefas NXC Um programa consiste em mais de 255 tarefas, cada uma delas tem um nome único. A tarefa principal chamado deve sempre existe, porque esta é a primeira tarefa a ser executada. As demais tarefas serão executadas somente quando executando uma tarefa diz que elas sejam executadas ou estão expressamente prevista na principal; principal tarefa deve terminar antes de poderem iniciar. A partir desse momento, ambas as funções estão sendo executados simultaneamente. Deixe-me mostrar o uso de tarefas. Queremos fazer um programa em que o robô em torno de unidades em praças, como antes. Mas quando se atinge um obstáculo que deve reagir a ela. É difícil fazer isso em uma tarefa, uma vez que o robô deve fazer duas coisas ao mesmo tempo: cerca de unidade (isto é, mudar motores ligar e desligar no tempo) e relógio de sensores. Então é melhor usar duas funções para isso, uma tarefa que se move em praças, sendo que o outro que reage à sensores. Aqui está o programa. mutex moveMutex; task move_square() { while (true) { Acquire(moveMutex); OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(500); Release(moveMutex); } } task check_sensors() { while (true) { if (SENSOR_1 == 1) { Acquire(moveMutex); OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 75); Wait(500); Release(moveMutex); } } } task main() { Precedes(move_square, check_sensors); SetSensorTouch(IN_1); } A principal tarefa só define o tipo de sensor e, em seguida, inicia ambas as outras tarefas, adicionando-os na fila do agendador; após isto, principal tarefa termina. Tarefa move_square move o robô sempre nas praças. Tarefa check_sensors controlos se o toque sensor é empurrado e, nesse caso, leva o robô afastado obstáculo. É muito importante lembrar que iniciou funções estão executando no mesmo momento e isso pode levar a resultados inesperados, se ambas as funções estão tentando mover motores, uma vez que se destinam a fazer. Para evitar esses problemas, é declarado um estranho tipo de variável, mutex (que corresponde a exclusão mútua): nós pode agir sobre este tipo de variáveis só com a
  • 24. 24 aquisição e lançamento funções, escrita crítica pedaços de código entre estas funções, garantindo que apenas uma tarefa em um tempo pode ter um controlo total sobre motores. Estas variáveis são de tipo mutex chamado Semáforos e esta técnica é chamada de programação concorrente programação; este argumento é descrito em pormenor no capítulo 10. Sub-Rotinas Às vezes você precisa do mesmo pedaço de código em vários lugares em seu programa. Neste caso você pode colocar o pedaço de código em uma sub-rotina e dar- lhe um nome. Agora você pode executar esse pedaço de código, simplesmente chamar a sua nome de dentro de uma tarefa. Vejamos um exemplo. sub turn_around(int pwr) { OnRev(OUT_C, pwr); Wait(900); OnFwd(OUT_AC, pwr); } task main() { OnFwd(OUT_AC, 75); Wait(1000); turn_around(75); Wait(2000); turn_around(75); Wait(1000); turn_around(75); Off(OUT_AC); } Neste programa, temos definida uma sub-rotina que faz com que o robô gire em torno de seu centro. A principal tarefa exige a sub-rotina três vezes. Note que nós chamamos a sub-rotina escrevendo seu nome e passar uma numéricos argumento é escrito dentro seguintes parênteses. Se uma sub-rotina não aceita argumentos, basta adicionar parênteses sem nada dentro deles. Por isso, parece o mesmo que muitos dos comandos que temos visto. O principal benefício da sub-rotinas é que eles são armazenados apenas uma vez no NXT e isso economiza memória. Mas quando sub-rotinas são curtos, pode ser melhor usar funções inline vez. Estes não são armazenados separadamente, mas é copiado em cada local são usados. Este utiliza mais memória, mas não há limite para o número de funções inline. Eles pode ser declarado como segue: inline int Name( Args ) { //body; return x*y; } Definindo e chamando funções inline vai exactamente da mesma forma que com sub-rotinas. Portanto, o exemplo acima, usando inline funções, tem o seguinte aspecto: inline void turn_around() { OnRev(OUT_C, 75); Wait(900);
  • 25. 25 OnFwd(OUT_AC, 75); } task main() { OnFwd(OUT_AC, 75); Wait(1000); turn_around(); Wait(2000); turn_around(); Wait(1000); turn_around(); Off(OUT_AC); } No exemplo acima, podemos fazer o tempo para transformar um argumento da função, como nos seguintes exemplos: inline void turn_around(int pwr, int turntime) { OnRev(OUT_C, pwr); Wait(turntime); OnFwd(OUT_AC, pwr); } task main() { OnFwd(OUT_AC, 75); Wait(1000); turn_around(75, 2000); Wait(2000); turn_around(75, 500); Wait(1000); turn_around(75, 3000); Off(OUT_AC); } Note que no parêntese para trás o nome da função inline especificamos o argumento da (s) função. Em neste caso, indicar que o argumento é um inteiro (existem algumas outras opções) e que seu nome é turntime. Quando há mais argumentos, você deve separá-los com vírgulas. Note que em NXC, sub é o mesmo nulos, que também pode ter outras funções tipo de retorno do que nula, também pode retornar inteiro ou string valores para o chamador: para obter mais informações, consulte o Guia NXC. Definindo macros Existe ainda uma outra forma de dar pequenos pedaços de código de um nome. Você pode definir macros em NXC (a não ser confundidas com as macros em BricxCC). Vimos antes que possamos definir constantes, usando # define, por dando- lhes um nome. Mas na verdade podemos definir qualquer pedaço de código. Aqui é o mesmo programa novamente, mas agora usando uma macro para se virando. #define turn_around OnRev(OUT_B, 75); Wait(3400);OnFwd(OUT_AB, 75); task main() {
  • 26. 26 OnFwd(OUT_AB, 75); Wait(1000); turn_around; Wait(2000); turn_around; Wait(1000); turn_around; Off(OUT_AB); } Após a declaração # define a palavra turn_around defende o texto por trás dele. Agora, sempre que você digita turn_around, este é substituído pelo presente texto. Note que o texto deve estar em uma linha. (Na verdade, existem maneiras de colocando uma # define declaração em várias linhas, mas isto não é recomendado.) Definir declarações são realmente muito mais poderoso. Eles também podem ter argumentos. Por exemplo, podemos colocar a tempo para ativar como um argumento na declaração. Aqui está um exemplo em que se definem quatro macro's, um para mover em frente, um para mover para trás, um a virar à esquerda e um de virar à direita. Cada um tem dois argumentos: a velocidade e o tempo #define turn_right(s,t) OnFwd(OUT_A, s);OnRev(OUT_B, s);Wait(t); #define turn_left(s,t) OnRev(OUT_A, s);OnFwd(OUT_B, s);Wait(t); #define forwards(s,t) OnFwd(OUT_AB, s);Wait(t); #define backwards(s,t) OnRev(OUT_AB, s);Wait(t); task main() { backwards(50,10000); forwards(50,10000); turn_left(75,750); forwards(75,1000); backwards(75,2000); forwards(75,1000); turn_right(75,750); forwards(30,2000); Off(OUT_AB); } É muito útil para definir essas macros. Faz o seu código mais compacto e legível. Além disso, você pode obter mais facilmente alterar o seu código quando você e.g. mudar as conexões dos motores. Resumo Neste capítulo você viu o uso de funções, subrotinas, funções inline, e macros. Eles têm várias utilizações. Tarefas normalmente executado no mesmo momento e cuidar de coisas diferentes que têm de ser feito no mesmo momento. Subrotinas são úteis quando grandes pedaços de código deve ser utilizado em locais diferentes na mesma tarefa. Inline funções são úteis quando pedaços de código deve ser utilizado um muitos lugares diferentes em diferentes tarefas, mas usam mais memória. Finalmente macros são muito úteis para pequenos pedaços de código que deve ser utilizado um lugares diferentes. Eles também podem ter parâmetros, tornando-os ainda mais útil. Agora que você tem trabalhado através dos capítulos até aqui, você tem todas as habilidades que você precisa para fazer seu robô fazer as coisas complicadas. Os outros capítulos neste tutorial ensinar-vos acerca de outras coisas que são importantes apenas em determinadas aplicações. 7. Fazendo música
  • 27. 27 O NXT tem um alto-falante que pode reproduzir tons e mesmo ficheiros de som. Trata-se, em especial útil quando você quero fazer o NXT dizer-lhe que algo está acontecendo. Mas também pode ser engraçado para que o robô faça música ou falar ao mesmo tempo que corre ao redor. Reproduzir arquivos sonoros BricxCC tem incorporado um elemento de utilidade para converter. Wav em. RSO arquivos acessíveis via menu Som conversão.Ferramentas Então você pode armazenar. RSO arquivos sonoros sobre NXT memória flash usando outro utilitário, o NXT memória navegador NXT Explorer) e reproduzi-los com o comando(Ferramentas PlayFileEx(filename, volume, loop?) Os seus argumentos são sólidos filename, volume (um número de 0 a 4), e loop: este último argumento é definido como 1 (TRUE) se quiser que o arquivo a ser furado ou 0 (FALSO) se você quiser reproduzi-lo somente uma vez. #define TIME 200 #define MAXVOL 7 #define MINVOL 1 #define MIDVOL 3 #define pause_4th Wait(TIME) #define pause_8th Wait(TIME/2) #define note_4th PlayFileEx("! Click.rso",MIDVOL,FALSE); pause_4th #define note_8th PlayFileEx("! Click.rso",MAXVOL,FALSE); pause_8th task main() { PlayFileEx("! Startup.rso",MINVOL,FALSE); Wait(2000); note_4th; note_8th; note_8th; note_4th; note_4th; pause_4th; note_4th; note_4th; Wait(100); } Este belo programa reproduz a primeira música que você pode iniciar já sabe, então usa a outra norma clique som para jogar "barbear e um corte de cabelo" jingle que fez Roger Rabbit go crazy! As macros são realmente úteis, neste caso, para simplificar a notação das principais tarefas: tentar modificar as configurações de volume para adicionar acentos na melodia. Reproduzir música Para reproduzir um tom, você pode utilizar o comando PlayToneEx(frequency, duration, volume, loop?) Tem quatro argumentos. A primeira é a frequência em Hertz, o segundo, a duração (em 1 / 1000 de um segundo, como no aguardar o comando), e o último volume são um loop como antes. PlayTone(frequency, duration) também pode ser utilizada; neste caso, o volume é o fixado pelo NXT um menu, eo circuito está desativado. Aqui está uma tabela de frequências útil: Sound 3 4 5 6 7 8 9 B 247 494 988 1976 3951 7902 A# 233 466 932 1865 3729 7458 A 220 440 880 1760 3520 7040 14080
  • 28. 28 G# 415 831 1661 3322 6644 13288 G 392 784 1568 3136 6272 12544 F# 370 740 1480 2960 5920 11840 F 349 698 1397 2794 5588 11176 E 330 659 1319 2637 5274 10548 D# 311 622 1245 2489 4978 9956 D 294 587 1175 2349 4699 9398 C# 277 554 1109 2217 4435 8870 C 262 523 1047 2093 4186 8372 Tal como acontece com o caso de PlayFileEx, o NXT, não espere que a nota para terminar. Portanto, se você usar vários tons na uma linha, então você teve melhor acrescentar (pouco mais) entre em esperar comandos. Aqui está um exemplo: #define VOL 3 task main() { PlayToneEx(262,400,VOL,FALSE); Wait(500); PlayToneEx(294,400,VOL,FALSE); Wait(500); PlayToneEx(330,400,VOL,FALSE); Wait(500); PlayToneEx(294,400,VOL,FALSE); Wait(500); PlayToneEx(262,1600,VOL,FALSE); Wait(2000); } Você pode criar peças de música muito facilmente utilizando o Brick Piano que faz parte do BricxCC. Se quiser ter o NXT ouvir música enquanto estiver dirigindo por aí, melhor usar uma tarefa separada para ele. Aqui você tem uma exemplo de um programa onde o bastante estúpido NXT drives para frente e para trás, constantemente fazer música. task music() { while (true) { PlayTone(262,400); Wait(500); PlayTone(294,400); Wait(500); PlayTone(330,400); Wait(500); PlayTone(294,400); Wait(500); } } task movement() { while(true) { OnFwd(OUT_AC, 75); Wait(3000); OnRev(OUT_AC, 75); Wait(3000); } } task main() { Precedes(music, movement); } Resumo Neste capítulo você aprendeu a deixar o NXT reproduzir sons e música. Também você viu como usar uma tarefa para música. 8. Mais informações sobre os motores
  • 29. 29 Há um número adicional de motor comandos que você pode usar para controlar os motores com mais precisão. Neste capítulo, discuti-las: ResetTachoCount, Costa (float), OnFwdReg, OnRevReg, OnFwdSync, OnRevSync, RotateMotor, RotateMotorEx, e conceitos básicos PID. Paragem suave Quando você usa o Off() comando, o servo motor pára imediatamente, travagem do eixo e exploração posição. Também é possível parar o motor em uma maneira mais suave, não utilizando o freio. Para esta utilização Float() ou Coast() comando mediocremente, simples que retira o poder fluir a motor. Aqui está um exemplo. Primeiro o robô pára de usar os freios; próxima sem utilizar os travões. Observe a diferença. Na verdade, a diferença é muito pequena especial para esse robô. Mas ela faz uma grande diferença para alguns outros robôs. task main() { OnFwd(OUT_AC, 75); Wait(500); Off(OUT_AC); Wait(1000); OnFwd(OUT_AC, 75); Wait(500); Float(OUT_AC); } Comandos Avançados Os comandos OnFwd() e OnRev() são as rotinas mais simples para mover motores. O NXT servomotores possuem um codificador built-in que permite que você controle precisamente veio posição e velocidade; NXT firmware implementa um PID (Proportional Integrative Derivative) de ciclo fechado controlador para controlar motores' posição e velocidade usando encoders como feedback. Se você deseja que seu robô para ir perfeitamente reto, você pode usar um recurso que faz a sincronização selecionados casal de motores para funcionar em conjunto e esperar uns dos outros, no caso um deles seja abrandado, ou mesmo bloqueado, em um mesma forma, você pode definir um par de motores para funcionar em conjunto em sincronia, com uma percentagem de orientar a virar à esquerda, direita ou girar no lugar, mas sempre mantendo sinc. Existem muitos comandos para libertar servomotores «plenos poderes! OnFwdReg(‘ports',‘speed',‘regmode') leva o motor especificado por" portos ", em 'velocidade' poder Modo de aplicação do regulamento que pode ser tanto OUT_REGMODE_IDLE, OUT_REGMODE_SPEED OUT_REGMODE_SYNC. INACTIVIDADE Se for selecionado, não PID regulamento serão aplicadas; VELOCIDADE se está seleccionado o modo, o NXT regulamenta único motor para obter uma velocidade constante, mesmo quando a carga no motor varia, finalmente, se SYNC é selecionada, o casal de motores especificados por "portos" mover em sincronia como explicado antes. OnRevReg()funciona como o precedente comando, inverter direção. task main() { OnFwdReg(OUT_AC,50,OUT_REGMODE_IDLE);
  • 30. 30 Wait(2000); Off(OUT_AC); PlayTone(4000,50); Wait(1000); ResetTachoCount(OUT_AC); OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED); Wait(2000); Off(OUT_AC); PlayTone(4000,50); Wait(1000); OnFwdReg(OUT_AC,50,OUT_REGMODE_SYNC); Wait(2000); Off(OUT_AC); } Este programa mostra bem diferente regulamentação, se tentar parar de rodas segurando o robô em suas mãos: em primeiro lugar (Modo de espera), parando uma roda que você não vai notar nada; depois (modo de velocidade), a tentativa de abrandar um roda, você verá que o motor NXT aumenta o poder de superar a sua espera, a tentar manter a velocidade constante; finalmente (SINC mode), parando uma roda fará com que o outro para uma parada, à espera que o bloqueou um. OnFwdSync(‘ports',‘speed',‘turnpct') é o mesmo que OnFwdReg() no comando SYNC modalidade, mas agora você também pode especificar a «turnpct« direcção percentual (de -100 a 100). OnRevSync() é o mesmo que antes, simplesmente inverter o motor da direcção. O programa seguinte mostra estes comandos: tente mudar direcção número para ver como se comporta. task main() { PlayTone(5000,30); OnFwdSync(OUT_AC,50,0); Wait(1000); PlayTone(5000,30); OnFwdSync(OUT_AC,50,20); Wait(1000); PlayTone(5000,30); OnFwdSync(OUT_AC,50,-40); Wait(1000); PlayTone(5000,30); OnRevSync(OUT_AC,50,90); Wait(1000); Off(OUT_AC); } Finalmente, motores pode ser configurado para ligar a um número limitado de graus (lembre-se que uma volta completa é 360 °). Para ambos os seguintes comandos, você pode agir em direção a motor da mudança, quer o sinal da velocidade ou o sinal do ângulo: assim, se a velocidade eo ângulo tem mesmo sinal, motor irá correr em frente, se o seu sinal é oposto, o motor irá correr para trás. RotateMotor(‘ports',‘speed',‘degrees')gira eixo do motor especificada pelo 'portas' por um' graus' ângulo em 'velocidade' poder (no intervalo 0-100). task main() { RotateMotor(OUT_AC, 50,360); RotateMotor(OUT_C, 50,-360); } RotateMotorEx(‘ports',‘speed',‘degrees',‘turnpct',‘sync', 'stop')is an extension of theprecedent command, that lets you synchronize two motors (e.g. OUT_AC) specifying a ‘turnpct'steering percentage (from -100 to 100) and a boolean flag ‘sync'
  • 31. 31 (that can be set to true or false). It also lets youspecify whether the motors should brake after the angle of rotation has completed using the boolean flag 'stop'. task main() { RotateMotorEx(OUT_AC, 50, 360, 0, true, true); RotateMotorEx(OUT_AC, 50, 360, 40, true, true); RotateMotorEx(OUT_AC, 50, 360, -40, true, true); RotateMotorEx(OUT_AC, 50, 360, 100, true, true); } Controle PID NXT firmware implementa uma digital PID (proporcional integrativo derivados) controlador para regular servomotores' posição e velocidade com precisão. Este tipo de controlador é um dos mais simples ainda mais eficaz em circuito fechado feedback controlador automação é conhecida, e é frequentemente utilizado. Nas palavras grosseiras, funciona assim (vou falar sobre regulação para uma posição discreta tempo controlador): Seu programa dá o controlador um ponto de referência R (t) para alcançar e que acciona o motor com um comando U (t), medição da sua posição Y (t), com o built- in codificador e calcula um erro E (t) = R (t) - Y (t): aqui é a razão pela qual é chamado de "ciclo fechado controlador", porque a posição de saída Y (t) é trazida de volta para o controlador de entrada para calcular o erro. O controlador transforma o erro E (t) para o comando U (t) de modo: U(t) = P(t) + I(t) + D(t), where P(t) = KP·E(t), I(t) = KI·( I(t–1) + E(t) ) and D(t) = KD·(E(t) – E(t –1)). Pode parecer muito difícil para um iniciante, mas vou tentar explicar o mecanismo da melhor forma que posso. O comando é a soma de três contribui, a parte proporcional P (t), a integradora parte I (t) e do derivado parte D (t). P (t) faz com que o controlador em tempo rápido, mas não garanto um erro nulo no equilíbrio; I (t) dá "memória" para o controlador, no sentido em que assume traços de erros acumulados e compensa eles, com a garantia de um erro zero de equilíbrio; D (t), dá "futuro previsão" para o controlador (como derivação em matemática), acelerando a resposta. Eu sei que isto ainda pode ser confuso, consideram que todo acadêmico livros foram escritos sobre este argumento! Mas ainda podemos experimentá-lo on-line, com os nossos NXT tijolo! O programa simples de corrigir as coisas para a memória é o seguinte. #define P 50 #define I 50 #define D 50 task main() { RotateMotorPID(OUT_A, 100, 180, P, I, D); Wait(3000); } O RotateMotorPID(port,speed, angle, Pgain,Igain,Dgain) permitem-lhe mover um motor configuração diferente PID ganhos a partir do padrão queridos. Tente definir os seguintes valores
  • 32. 32 (50,0,0): o motor não girar 180 °, exactamente, uma vez que um erro continua descompensada (0, x, x): sem a parte proporcional, o erro é muito grande (40,40,0): há uma superação, o que significa eixo do motor se move para além do set point e então vira costas (40,40,90): uma boa precisão e aumento do tempo (tempo para chegar ao set point) (40,40200): o eixo oscilar, pois derivado ganho é muito alto Experimente outros valores para descobrir como estes ganhos influência um desempenho do motor. Resumo Neste capítulo você aprendeu sobre o avançado motor comandos disponíveis: float (), Costa () que parar o motor suavemente; OnXxxReg (), e OnXxxSync () que permite o controlo sobre motores feedback 'velocidade e sincronização; RotateMotor () e RotateMotorEx () são usados para ligar o motor veio por um número exacto de graus. Você Aprendi algo sobre controle PID também, não foi uma explicação exaustiva, mas talvez tenha causado um pouco de curiosidade em você: pesquisa na web sobre ela! 9. Mais informações sobre os sensores No capítulo V, discutimos os aspectos básicos do uso de sensores. Mas há muito mais que você pode fazer com sensores. Em este capítulo vamos discutir a diferença entre o modo de sensor e sensor tipo, vamos ver como usar os antigos compatível RCX sensores, anexando-os a utilizar Lego NXT conversor cabos. Sensor modalidade e tipo O SetSensor () comando que vimos antes realmente faz duas coisas: que define o tipo de sensor, e ele define o modo em que o sensor atua. Ao definir o modo eo tipo de um sensor separadamente, você pode controlar o comportamento do sensor de forma mais precisa, o que é útil para determinadas aplicações. O tipo de sensor é definido com o comando SetSensorType (). Existem muitos tipos diferentes, mas vou relatório os principais: SENSOR_TYPE_TOUCH, que é o toque sensor, SENSOR_TYPE_LIGHT_ACTIVE, que é o sensor de luz (com LED ligado), SENSOR_TYPE_SOUND_DB, que é o som sensor, e SENSOR_TYPE_LOWSPEED_9V, que é o sensor ultra-sônico. Definir o tipo de sensor é especialmente importante para indicar se o sensor tem poder (por exemplo, para acender conduziram à luz sensor), ou para indicar que o NXT sensor é digital e deve ser lido através do protocolo serial I2C. É possível utilizar o antigo RCX sensor com NXT: SENSOR_TYPE_TEMPERATURE, para o sensor de temperatura, luz SENSOR_TYPE_LIGHT para antigos sensor, SENSOR_TYPE_ROTATION para RCX rotação sensor (este tipo será discutido mais tarde). O modo do sensor é definido com o comando SetSensorMode (). Há oito modos diferentes. O mais é um importante SENSOR_MODE_RAW. Neste modo, o valor que você começa quando a verificação do sensor é um número entre 0 e 1023. É o valor bruto produzido pelo sensor. O que isso significa que depende do próprio sensor. Para exemplo, para tocar um sensor, quando o sensor não é empurrada para o valor está perto de 1023. Quando estiver plenamente empurrado, ele está perto de 50. Quando é
  • 33. 33 empurrado parcialmente o valor varia entre 50 e 1000. Portanto, se você definir um sensor de toque modo raw você pode realmente saber se é tocado parcialmente. Quando o sensor é um sensor luz, o valor varia de cerca de 300 (muito leve) a 800 (muito escuro). Isto dá um valor muito mais precisas do que usando o SetSensor () comando. Para mais informações, consulte o Guia NXC Programação. O segundo modo é SENSOR_MODE_BOOL sensor. Neste modo, o valor é 0 ou 1. Quando o valor bruto é superior a 562 o valor é 0, caso contrário, ela é de 1. SENSOR_MODE_BOOL é o modo padrão para um toque sensor, mas pode ser utilizado para outros tipos, descartando informação analógica. Os modos SENSOR_MODE_CELSIUS e SENSOR_MODE_FAHRENHEIT são úteis somente com sensores de temperatura e dê a temperatura indicada no maneira. SENSOR_MODE_PERCENT transforma o valor bruto em um valor entre 0 e 100. SENSOR_MODE_PERCENT é o modo padrão para uma luz sensor. SENSOR_MODE_ROTATION só é utilizado para a rotação sensor (ver abaixo). Existem dois outros modos interessantes: SENSOR_MODE_EDGE e SENSOR_MODE_PULSE. Eles contam transições, isto é, as mudanças de uma baixa para um alto valor bruto ou oposto. Por exemplo, quando você tocar um toque sensor presente provoca uma transição de alto a baixo valor bruto. Quando você libertá-lo, obtém uma transição a outra direção. Quando você define o sensor de modo SENSOR_MODE_PULSE, só a partir de transições de baixa a alta são contadas. Assim, cada toque e liberação da conta para um sensor toque. Quando você define o sensor de modo SENSOR_MODE_EDGE, ambas as transições são contadas. Assim, cada toque e liberação da touch sensor para duas contagens. Então você pode usar esse recurso para contar quantas vezes um toque sensor é empurrado. Ou você pode usá-lo em combinação com um sensor de luz contam como muitas vezes uma (forte) lâmpada é ligada e desligada. Claro, quando você está contando arestas ou pulsos, deverá ser capazes de definir o contador volta a 0. Para isso, você use o comando ClearSensor (), que apura o contador para o indicado sensor. Vejamos um exemplo. O seguinte programa usa um sensor toque para orientar o robô. Ligue o toque sensor com um longo fio de uma entrada. Se tocar o sensor rapidamente duas vezes o robot se move em frente. Por que você lhe toque quando ele pára de se mover. task main() { SetSensorType(IN_1, SENSOR_TYPE_TOUCH); SetSensorMode(IN_1, SENSOR_MODE_PULSE); while(true) { ClearSensor(IN_1); until (SENSOR_1 > 0); Wait(500); if (SENSOR_1 == 1) {Off(OUT_AC);} if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);} } } Note que primeiro definir o tipo de sensor e, em seguida, o modo. Parece que isto é essencial porque mudar O tipo também afecta o modo. A rotação sensor
  • 34. 34 A rotação é um sensor muito útil tipo de sensor: é um encoder óptico, quase o mesmo que construir um dentro NXT servomotores. A rotação sensor contém um buraco através do qual você pode colocar um eixo, cujo parente posição angular é medido. Uma rotação completa do eixo contagens 16 passos (-16 ou se ele rodar a outra forma), o que significa uma resolução 22,5 graus, muito áspera relação ao 1-grau resolução do servomotor. Este antigo tipo de rotação sensor pode ser ainda útil para monitorar um eixo, sem a necessidade de um motor de resíduos; também considerar que usando um motor como codificador requer uma grande quantidade de torque para movê- lo, enquanto antigo rotação sensor é muito fácil de rodar. Se você precisar de mais finas resolução superior a 16 passos por sua vez, você sempre pode usar artes mecanicamente para aumentar o número de carrapatos por turno. Seguinte exemplo é herdado do antigo tutorial para RCX. Uma aplicação padrão é ter dois sensores conectados à rotação duas rodas do robô que você controle com os dois motores. Para um movimento rectilíneo quiser para ligar as duas rodas igualmente rápido. Infelizmente, os motores normalmente não são executados em exatamente a mesma velocidade. Utilizando sensores de rotação que você pode ver que uma roda voltas mais rápidas. Em seguida, você pode interromper temporariamente a que o motor (melhor usar Float ()) até que ambos os sensores dar a mesma valor novamente. O seguinte programa faz isso. Ele simplesmente permite que o robô em uma unidade da linha recta. Para usá-lo, mudar seu robot, ligando os dois sensores de rotação das duas rodas. Ligue a entrada dos sensores 1 e 3. task main() { SetSensor(IN_1, SENSOR_ROTATION); ClearSensor(IN_1); SetSensor(IN_3, SENSOR_ROTATION); ClearSensor(IN_3); while (true) { if (SENSOR_1 < SENSOR_3) { OnFwd(OUT_A, 75); Float(OUT_C); } else if (SENSOR_1 > SENSOR_3) { OnFwd(OUT_C, 75); Float(OUT_A); } else { OnFwd(OUT_AC, 75); } } } O programa, primeiro indica que ambos os sensores são sensores rotação, e redefine os valores a zero. Em seguida é iniciado um loop infinito. No laço que verifique se o sensor duas leituras são iguais. Se eles são o robô simplesmente jogadas frente. Se um é maior, o correto motor está parado até duas leituras são novamente iguais. É evidente que isto só é um programa muito simples. Você pode estender isso para fazer o robô unidade distâncias exatas, ou a deixar é preciso fazer muito gira. Colocar vários sensores em uma entrada
  • 35. 35 Um pouco de renúncia é necessária no início desta secção! Devido à nova estrutura de melhores NXT sensores e 6 -- fios cabos, não é fácil como antes (como foi para RCX) para conectar mais sensores para o mesmo porto. Na minha honesta opinião, a única confiável (e fácil de fazer) seria pedido para construir um toque sensor analógico multiplexer de usar em combinação com um conversor cabo. A alternativa é um complexo multiplexer digital que pode gerenciar I2C comunicação com NXT, mas este não é definitivamente uma solução acessível para os principiantes. O NXT tem quatro entradas para ligar sensores. Quando você quiser tornar mais complicado robôs (e que você comprou alguns extras sensores), este poderá não ser suficiente para você. Felizmente, com alguns truques, você pode ligar duas (ou ainda mais) sensores para uma entrada. O mais fácil é para ligar dois sensores de toque uma entrada. Se um deles (ou ambos), é abordado o valor for 1, caso contrário é 0. Você não pode distinguir os dois, mas às vezes isso não é necessário. Por exemplo, quando você colocar um toque sensor na parte dianteira e um na parte de trás do robô, você sabe o que é tocado um baseado no direcção do robot está dirigindo pol Mas você também pode definir o modo de entrada para as matérias-primas (veja acima). Agora você pode começar muito mais informações. Se você é sortudo, o valor é pressionada quando o sensor não é a mesma para ambos os sensores. Se é este o caso, você pode realmente distinguir entre os dois sensores. E quando ambos são pressionadas você obterá um grande menor valor (cerca de 30) para que você também pode detectar isto. Você também pode ligar um toque sensor e um sensor de luz uma entrada (RCX sensores apenas). Defina o tipo de luz (caso o sensor de luz não irá funcionar). Defina o modo de matérias-primas. Neste caso, quando o toque sensor é empurrada para você obter um valor bruto inferior a 100. Caso não seja empurrada para você obter o valor de o sensor de luz, que nunca é inferior a 100. O programa seguinte utiliza esta ideia. O robô deve ser equipado com um sensor luz apontando para baixo, e um pára-choques à frente ligado a um sensor toque. Conecte a entrada de ambos 1. O robô terá unidade em torno de aleatoriamente dentro de uma luz área. Quando o sensor de luz vê uma linha escura (valor bruto> 750) que vai voltar um pouco. Quando o toque sensor toque algo (valor bruto inferior a 100) que faz o mesmo. Aqui está o programa: mutex moveMutex; int ttt,tt2; task moverandom() { while (true) { ttt = Random(500) + 40; tt2 = Random(); Acquire(moveMutex); if (tt2 > 0) { OnRev(OUT_A, 75); OnFwd(OUT_C, 75); Wait(ttt); } else { OnRev(OUT_C, 75); OnFwd(OUT_A, 75); Wait(ttt); } ttt = Random(1500) + 50; OnFwd(OUT_AC, 75); Wait(ttt); Release(moveMutex); } } task submain()
  • 36. 36 { SetSensorType(IN_1, SENSOR_TYPE_LIGHT); SetSensorMode(IN_1, SENSOR_MODE_RAW); while (true) { if ((SENSOR_1 < 100) || (SENSOR_1 > 750)) { Acquire(moveMutex); OnRev(OUT_AC, 75); Wait(300); Release(moveMutex); } } } task main() { Precedes(moverandom, submain); } Espero que o programa é muito claro. Existem duas tarefas. Tarefa moverandom faz com que o robô se deslocar em um aleatória maneira. A principal tarefa primeiro começa moverandom, estabelece que o sensor e, em seguida, espera por alguma coisa para acontecer. Se o sensor leitura fica demasiado baixo (tocar) ou muito alta (fora da área branca) ele pára a movimentos aleatórios, faz o backup de um pouco, e começar a aleatórias jogadas novamente. Resumo Neste capítulo, temos visto uma série de questões adicionais sobre sensores. Vimos como separadamente para definir o tipo e modo de um sensor e como isso poderia ser utilizado para obter informações aditamentos. Aprendemos como utilizar o rotação sensor. E vimos como múltiplos sensores podem ser conectados a uma entrada do NXT. Todos estes truques são extremamente útil quando se mais complicada robôs. Sensores sempre desempenhar um papel crucial lá. 10. tarefas paralelas Como já foi indicado antes, em NXC tarefas são executadas em simultâneo, ou em paralelo à medida que as pessoas geralmente dizem. Isto é extremamente útil. Nos sensores permite que você preste atenção a uma tarefa em outra tarefa enquanto se move em torno do robô, e ainda uma outra tarefa desempenha algumas músicas. Mas, paralelamente tarefas também podem causar problemas. Uma tarefa pode interferir com outro. Um programa errado Considere o seguinte programa. Aqui uma tarefa unidades ao redor do robô em praças (como fizemos tantas vezes antes) e a segunda tarefa verifica a tocar sensor. Quando o sensor é tocado, desloca-se um pouco para trás, e faz um 90-grau turno. task check_sensors() { while (true) { if (SENSOR_1 == 1) { OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 75); Wait(850);
  • 37. 37 OnFwd(OUT_C, 75); } } } task submain() { while (true) { OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(500); } } task main() { SetSensor(IN_1,SENSOR_TOUCH); Precedes(check_sensors, submain); } Este é, provavelmente parecido com um programa perfeitamente válido. Mas se você executá-lo você provavelmente irá encontrar alguns um comportamento inesperado. Experimente o seguinte: Faça o robô tocar alguma coisa enquanto ela estiver rodando. Ela vai começar a ir volta, mas logo se move em frente de novo, batendo o obstáculo. A razão para isto é que as tarefas podem interferir. A seguir está a acontecer. O robô está rodando direito, isto é, a primeira tarefa é, em sua segunda sono declaração. Agora, o robô atinge o sensor. Ela vai começar para trás, mas em que momento, a tarefa principal é pronto com sono e move o robô envia novamente; para o obstáculo. A segunda tarefa está dormindo a esta momento por isso não irá detectar a colisão. Isto não é claramente o comportamento que gostaríamos de ver. O problema é que, enquanto a segunda tarefa está dormindo nós não percebemos que a primeira tarefa era ainda em execução, e que as suas acções interferem com as ações da segunda tarefa. Secções críticas e variáveis mutex Uma maneira de resolver este problema é ter a certeza de que, em qualquer momento, apenas uma tarefa é conduzir o robô. Esta foi a abordagem que tomou no capítulo VI. Permitam-me repetir o programa aqui. mutex moveMutex; task move_square() { while (true) { Acquire(moveMutex); OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(850); Release(moveMutex); } } task check_sensors() { while (true) { if (SENSOR_1 == 1) { Acquire(moveMutex); OnRev(OUT_AC, 75);Wait(500); OnFwd(OUT_A, 75); Wait(850); Release(moveMutex); } } } task main() { SetSensor(IN_1,SENSOR_TOUCH); Precedes(check_sensors, move_square);
  • 38. 38 } O ponto crucial é que tanto o check_sensors e tarefas move_square podem controlar motores apenas se nenhuma outra tarefa é utilizá-los: isto é feito usando o Acquire declaração de que espera o moveMutex mútua exclusão variável a ser libertado antes de utilizar motores. A contrapartida é o comando Adquirir Release comando, que liberta o mutex variável tão outras tarefas podem usar o recurso crítico, motores, no nosso caso. O código dentro do acquirerelease âmbito de aplicação é chamado crítico região: crítica compartilhada significa que os recursos são utilizados. Desta forma tarefas não pode interferem uns com os outros. Usando Semáforos Existe uma alternativa à mão-fabricados mutex variáveis que é explícita a aplicação da aquisição e Lançamento comandos. Uma norma técnica para resolver este problema é utilizar uma variável para indicar qual a tarefa é o controle dos motores. As outras tarefas não estão autorizados a conduzir os motores até que a primeira tarefa indica, utilizando a variável, que é pronto. Essa variável é freqüentemente chamado um semáforo. Deixa sem ser essa uma semáforo (o mesmo que mutex). Assumimos que um valor de 0 indica que nenhuma tarefa é governar o motor (recurso é gratuito). Agora, sempre que uma tarefa quer fazer algo com os motores que executa os seguintes comandos: until (sem == 0); sem = 1; //Acquire(sem); // Do something with the motors // critical region sem = 0; //Release(sem); Por isso, primeiro ninguém precisa esperar até os motores. Então, o controlo através da definição de crédito sem a 1. Agora, pode controlar os motores. Quando estamos a fazer é definir sem volta para 0. Aqui você encontra o programa anterior, implementada através de um semáforo. Quando o sensor toque toca alguma coisa, o semáforo está definido e é o procedimento de backup realizada. Durante este processo, a tarefa move_square deve esperar. Neste momento, o back-up está pronta, o semáforo está definido para 0 e move_square pode continuar. int sem; task move_square() { while (true) { until (sem == 0); sem = 1; OnFwd(OUT_AC, 75); sem = 0; Wait(1000); until (sem == 0); sem = 1; OnRev(OUT_C, 75); sem = 0; Wait(850); } } task submain() { SetSensor(IN_1, SENSOR_TOUCH); while (true) { if (SENSOR_1 == 1) { until (sem == 0); sem = 1; OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 75); Wait(850); sem = 0; }
  • 39. 39 } } task main() { sem = 0; Precedes(move_square, submain); } Você poderia argumentar que não é necessário em move_square para definir o semáforo para 1 e de volta para 0. Ainda esta é útil. A razão é que o OnFwd () comando é, na realidade, dois comandos (ver capítulo VIII). Você não quer este comando seqüência deve ser interrompida pela outra tarefa. Semáforos são muito úteis e, quando está a escrever programas com paralelo tarefas complicadas, eles são quase sempre exigida. (Há ainda uma pequena chance que pode falhar. Tentar descobrir porquê.) Resumo Neste capítulo, estudamos alguns dos problemas que podem ocorrer quando você usa diferentes tarefas. Ser sempre muito cuidado para efeitos secundários. Muito inesperado comportamento é devido a isso. Vimos duas maneiras diferentes de resolver tais problemas. A primeira solução pára e reinicia tarefas para se certificar de que apenas uma tarefa crítica estiver sendo executado em todos os momento. A segunda abordagem utiliza Semáforos para controlar a execução das tarefas. Isso garante que, em cada momento, apenas a parte crítica de uma tarefa é executada. 11. A comunicação entre robôs Se você possui mais de um NXT este capítulo é para você (mas você pode ainda comunicar os dados para o PC, com uma única NXT). Robôs podem se comunicar uns com os outros via rádio Bluetooth tecnologia: você pode ter várias robôs colaborar (ou lutar uns com os outros), e você pode construir um robô usando dois grandes complexos NXTs, de modo que você pode utilizar seis motores e oito sensores. Para o bom velho RCX, é simples: ele envia uma mensagem e todos os robôs infravermelho próximo de recebê-la. Para NXT é toda uma outra coisa! Primeiro, você deve ligar duas ou mais NXTs (ou NXT para PC), com a onbrick menu Bluetooth e só então você poderá enviar mensagens para os dispositivos ligados. O NXT que inicia a conexão é chamado de mestre, e pode ter até 3 Escravo dispositivos conectados em linhas 1,2,3; Escravos sempre ver o Mestre conectado na linha 0. Você pode enviar mensagens para 10 caixas disponíveis. Mestre - Escravo mensagens Dois programas serão mostrados, um para o comandante, um para o escravo. Estes programas básicos irá ensinar-lhe como um rápido fluxo contínuo de corda mensagens podem ser geridas por um dois-NXT rede wireless. O capitão programa primeiro verifica se o slave está corretamente conectado na linha 1 (BT_CONN constante), utilizando BluetoothStatus(conn) função; depois constrói e envia mensagens com um prefixo M e um número crescente com SendRemoteString(conn,queue,string), enquanto recebe mensagens de escravos com ReceiveRemoteString(queue,clear,string) e apresenta dados.
  • 40. 40 //MASTER #define BT_CONN 1 #define INBOX 1 #define OUTBOX 5 sub BTCheck(int conn) { if (!BluetoothStatus(conn)==NO_ERR) { TextOut(5,LCD_LINE2,"Error"); Wait(1000); Stop(true); } } task main() { string in, out, iStr; int i = 0; BTCheck(BT_CONN); //check slave connection while(true) { iStr = NumToStr(i); out = StrCat("M",iStr); TextOut(10,LCD_LINE1,"Master Test"); TextOut(0,LCD_LINE2,"IN:"); TextOut(0,LCD_LINE4,"OUT:"); ReceiveRemoteString(INBOX, true, in); SendRemoteString(BT_CONN,OUTBOX,out); TextOut(10,LCD_LINE3,in); TextOut(10,LCD_LINE5,out); Wait(100); i++; } } O escravo programa é muito semelhante, mas utiliza SendResponseString (fila, corda) em vez de SendRemoteString porque escravo devem pode enviar mensagens apenas para o seu comandante, visto on-line 0. //SLAVE #define BT_CONN 1 #define INBOX 5 #define OUTBOX 1 sub BTCheck(int conn) { if (!BluetoothStatus(conn)==NO_ERR) { TextOut(5,LCD_LINE2,"Error"); Wait(1000); Stop(true); } } task main() { string in, out, iStr; int i = 0; BTCheck(0); //check master connection while(true) { iStr = NumToStr(i); out = StrCat("S",iStr); TextOut(10,LCD_LINE1,"Slave Test"); TextOut(0,LCD_LINE2,"IN:"); TextOut(0,LCD_LINE4,"OUT:"); ReceiveRemoteString(INBOX, true, in); SendResponseString(OUTBOX,out); TextOut(10,LCD_LINE3,in); TextOut(10,LCD_LINE5,out); Wait(100); i++; } }
  • 41. 41 Você irá notar que abortar um dos programas, os outros vão continuar a enviar mensagens com crescente números, sem saber que todas as mensagens enviadas serão perdidas, porque ninguém está a ouvir o outro lado. Para evitar esse problema, podemos programar um protocolo mais finas, com aviso de entrega. Enviando números com aviso Aqui vemos um outro par de programas: desta vez com o mestre envia números SendRemoteNumber (conn, fila, número) e parar de esperar por escravos ack (até ciclo, no qual estamos encontrar ReceiveRemoteString); slave apenas se está a ouvir e enviar ACKS, prossegue o mestre enviar o próximo mensagem. Escravo simplesmente recebe número com ReceiveRemoteNumber (fila, claro, o número) e envia o ack com SendResponseNumber. Seu mestre-escravo programas devem concordar sobre o Código Comum para a ack, neste caso, eu escolho a hex valor 0xFF. O mestre envia números aleatórios e aguarda por escravos ack; toda vez que receber um ack com o código correto, o ack variável deve ser apagada, caso contrário, o capitão vai continuar enviando sem novos ACKS, porque a variável tenho sujo. O escravo verifica continuamente a caixa de correio e, se não for vazio, exibe o valor lido e envia um ack para o mestre. No início do programa, eu optar por enviar um ack sem ler as mensagens para desbloquear o master; de facto, sem este artifício, se o capitão para o programa é iniciado primeiro, ele iria enforcar mesmo começamos escravo posterior. Desta forma as primeiras mensagens se perdem, mas você pode começar master e slave programas em diferentes momentos sem o risco de enforcamento. //MASTER #define BT_CONN 1 #define OUTBOX 5 #define INBOX 1 #define CLEARLINE(L) TextOut(0,L," "); sub BTCheck(int conn) { if (!BluetoothStatus(conn)==NO_ERR) { TextOut(5,LCD_LINE2,"Error"); Wait(1000); Stop(true); } } task main() { int ack; int i; BTCheck(BT_CONN); TextOut(10,LCD_LINE1,"Master sending"); while(true) { i = Random(512); CLEARLINE(LCD_LINE3); NumOut(5,LCD_LINE3,i); ack = 0; SendRemoteNumber(BT_CONN,OUTBOX,i); until(ack==0xFF) { until(ReceiveRemoteNumber(INBOX,true,ack)== NO_ERR); } Wait(250); } }
  • 42. 42 //SLAVE #define BT_CONN 1 #define OUT_MBOX 1 #define IN_MBOX 5 sub BTCheck(int conn) { if (!BluetoothStatus(conn)==NO_ERR) { TextOut(5,LCD_LINE2,"Error"); Wait(1000); Stop(true); } } task main() { int in; BTCheck(0); TextOut(5,LCD_LINE1,"Slave receiving"); SendResponseNumber(OUT_MBOX,0xFF); //unblock master while(true) { if (ReceiveRemoteNumber(IN_MBOX,true,in)!= STAT_MSG_EMPTY_MAILBOX) { TextOut(0,LCD_LINE3," "); NumOut(5,LCD_LINE3,in); SendResponseNumber(OUT_MBOX,0xFF); } Wait(10); //take breath (optional) } } Diretório comandos Há ainda uma outra característica arrefecer sobre comunicação Bluetooth: mestre pode controlar diretamente seus escravos. No próximo exemplo, o mestre envia ao escravo directo comandos para reproduzir sons e mover um automóvel, não há necessidade de um programa escravo, uma vez que é o firmware do NXT escravo para receber e gerenciar mensagens! //MASTER #define BT_CONN 1 #define MOTOR(p,s) RemoteSetOutputState(BT_CONN, p, s, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED, OUT_REGMODE_SPEED, 0, OUT_RUNSTATE_RUNNING, 0) sub BTCheck(int conn) { if (!BluetoothStatus(conn)==NO_ERR) { TextOut(5,LCD_LINE2,"Error"); Wait(1000); Stop(true); } } task main() { BTCheck(BT_CONN); RemotePlayTone(BT_CONN, 4000, 100); until(BluetoothStatus(BT_CONN)==NO_ERR); Wait(110); RemotePlaySoundFile(BT_CONN, "! Click.rso", false); until(BluetoothStatus(BT_CONN)==NO_ERR); //Wait(500); RemoteResetMotorPosition(BT_CONN,OUT_A,true); until(BluetoothStatus(BT_CONN)==NO_ERR); MOTOR(OUT_A,100); Wait(1000); MOTOR(OUT_A,0);
  • 43. 43 } Resumo Neste capítulo, estudamos alguns dos aspectos básicos da comunicação Bluetooth entre robôs: conectando dois NXTs, enviar e receber textos, números e à espera de entrega ackowledgments. Este último aspecto é muito importante quando um protocolo de comunicação seguro é necessário. Como característica adicional, você também aprendeu como enviar comandos para um escravo directo tijolo. XII. Mais comandos NXC tem uma série de comandos adicionais. Neste capítulo vamos discutir três tipos: a utilização do temporizador, Comandos para controlar a exibição, e da utilização de sistema de arquivos NXT. Tempo O NXT tem um temporizador que é executado continuamente. Este temporizador carrapatos em incrementos de 1 / 1000 de um segundo. Você pode obter o valor atual do temporizador com CurrentTick(). Aqui está um exemplo do uso de um temporizador. As seguintes programa permite que o robô tipo de unidade aleatória durante 10 segundos. task main() { long t0, time; t0 = CurrentTick(); do { time = CurrentTick()-t0; OnFwd(OUT_AC, 75); Wait(Random(1000)); OnRev(OUT_C, 75); Wait(Random(1000)); } while (time<10000); Off(OUT_AC); } Você pode querer comparar o programa com a uma dada no capítulo IV, que fez exatamente a mesma tarefa. O um com temporizadores é definitivamente mais simples. Timers são muito úteis como um substituto para um Wait()comando. Você pode dormir durante um determinado período de tempo ao redefinir um temporizador e espera, em seguida, até que ele chegue a um determinado valor. Mas você também pode reagir em outros eventos (por exemplo, de sensores), enquanto espera. O seguinte programa simples é um exemplo disto. Isso permite que o robô unidade até ou 10 segundos são passado, ou o toque sensor toca alguma coisa. task main() { long t3; SetSensor(IN_1,SENSOR_TOUCH); t3 = CurrentTick();
  • 44. 44 OnFwd(OUT_AC, 75); until ((SENSOR_1 == 1) || ((CurrentTick()-t3) > 10000)); Off(OUT_AC); } Não se esqueça que temporizadores trabalho em carrapatos de 1 / 1000 de um segundo, tal como o comando esperar. Matricial visor NXT características um tijolo preto e branco matricial ecrã com uma resolução de 100x64 pixels. Existem muitas API funções para desenhar texto strings, números, pontos, linhas, retângulos, círculos, e até mesmo imagens bitmap (. ric arquivos). O próximo exemplo tenta abranger todos estes casos. Pixel numeradas (0,0) é um canto inferior esquerdo. #define X_MAX 99 #define Y_MAX 63 #define X_MID (X_MAX+1)/2 #define Y_MID (Y_MAX+1)/2 task main() { int i = 1234; TextOut(15,LCD_LINE1,"Display", true); NumOut(60,LCD_LINE1, i); PointOut(1,Y_MAX-1); PointOut(X_MAX-1,Y_MAX-1); PointOut(1,1); PointOut(X_MAX-1,1); Wait(200); RectOut(5,5,90,50); Wait(200); LineOut(5,5,95,55); Wait(200); LineOut(5,55,95,5); Wait(200); CircleOut(X_MID,Y_MID-2,20); Wait(800); ClearScreen(); GraphicOut(30,10,"faceclosed.ric"); Wait(500); ClearScreen(); GraphicOut(30,10,"faceopen.ric"); Wait(1000); } Todas estas funções são bastante auto-explicativo, mas agora eu vou descrever em detalhe os seus parâmetros. ClearScreen() limpa a tela; NumOut(x, y, number) permite que você especifique coordenadas, e número; TextOut(x, y, string) trabalha como acima, mas saídas uma cadeia de texto GraphicOut(x, y, filename) mostra um bitmap. Ric arquivo CircleOut(x, y, radius) saídas de um círculo determinado pelas coordenadas do centro e raio; LineOut(x1, y1, x2, y2) desenha uma linha que vai do ponto (x1, x2) a (x2, y2) PointOut(x, y) coloca um ponto na tela RectOut(x, y, width, height) desenha um retângulo com o vértice no canto inferior esquerdo (x, y) e com o dimensões especificadas; ResetScreen() redefine o ecrã. File system O NXT pode escrever e ler arquivos, armazenados no seu memória flash. Então, você poderia salvar um datalog dados de sensores números ou ler durante o
  • 45. 45 programa execução. O único limite no número e dimensão arquivos é o tamanho do flash memória. NXT funções API permitem-lhe gerir ficheiros (criar, renomear, excluir, localizar), permitem-lhe ler e escrever texto strings, números e único bytes. No próximo exemplo, iremos ver como criar um arquivo, gravar nele cordas e renomeá-lo. Primeiro, o programa elimina arquivos com nomes vamos usar: não é um bom hábito (devíamos verificar para o arquivo existência, excluí-lo manualmente ou automaticamente escolher outro nome para o nosso trabalho arquivo), mas não há problema em nosso caso simples. Ela cria o nosso arquivo de CreateFile("Danny.txt", 512, fileHandle), especificando o nome, dimensão e um identificador para o arquivo, onde NXT firmware irá escrever um número para seu próprio uso. Então ele constrói cordas e escrever no arquivo com transporte regresso com WriteLnString(fileHandle,string,bytesWritten), onde todos os parâmetros devem ser variáveis. Finalmente, o processo é encerrado e renomeado. Lembre-se: um arquivo deve ser fechado antes de iniciar outra operação, por isso, se você criou um arquivo que você pode escrever para ele; se você quiser ler a partir dele, você deve fechá-lo e abri-lo com OpenFileRead()para apagar / renomeá-lo, você deve fechá-la. #define OK LDR_SUCCESS task main() { byte fileHandle; short fileSize; short bytesWritten; string read; string write; DeleteFile("Danny.txt"); DeleteFile("DannySays.txt"); CreateFile("Danny.txt", 512, fileHandle); for(int i=2; i<=10; i++ ) { write = "NXT is cool "; string tmp = NumToStr(i); write = StrCat(write,tmp," times!"); WriteLnString(fileHandle,write, bytesWritten); } CloseFile(fileHandle); RenameFile("Danny.txt","DannySays.txt"); } NXT Explorer, carregar DannySays.txt para PC e dar uma olhada. Para ver o resultado, vá para Ferramentas BricxCC Pronto para o próximo exemplo! Vamos criar uma tabela com os caracteres ASCII. task main() { byte handle; if (CreateFile("ASCII.txt", 2048, handle) == NO_ERR) { for (int i=0; i < 256; i++) { string s = NumToStr(i); int slen = StrLen(s); WriteBytes(handle, s, slen); WriteLn(handle, i); } CloseFile(handle); } }
  • 46. 46 Realmente simples, este programa cria o arquivo e, se não ocorreu nenhum erro, ele escreve um número de 0 a 255 (convertendo é a seqüência anterior) com WriteBytes (handle, s, sLen), que é outra maneira de escrever sem cordas carriage return; então, escreve o número que está com WriteLn (handle, valor), que acrescenta um retorno de carro. O resultado, que você pode ver como ASCII.txt antes de abrir com um editor de texto (como o Windows Notepad), é tão explicável: o número escrito como uma string é mostrada na forma legível por humanos, enquanto que o número escrito como hex valor é interpretado e apresentado como um código ASCII. Duas funções importantes continuam a ser revelou: ReadLnString para ler strings de arquivos e ReadLn a ler números. Agora para o exemplo para o primeiro: a tarefa principal CreateRandomFile chamadas subrotinas que gera um arquivo com números aleatórios do mesmo (escritas como strings); você pode comentar essa linha e usar uma outra mão-criado arquivo texto para este exemplo. Em seguida, a tarefa principal abre o arquivo para leitura, que lê uma linha de uma só vez até ao final do arquivo, chamando ReadLnString função e exibe texto. No CreateRandomFile subrotina que geram uma quantidade predefinida de números aleatórios, convertê-los para string e escrevê-los para o arquivo. O ReadLnString aceita um arquivo manusear e uma variável string como argumentos: após a chamada, o texto será conter uma linha de texto ea função irá retornar um código de erro, que pode utilizar para saber se o final do arquivo foi atingido. #define FILE_LINES 10 sub CreateRandomFile(string fname, int lines) { byte handle; string s; int bytesWritten; DeleteFile(fname); int fsize = lines*5; //create file with random data if(CreateFile(fname, fsize, handle) == NO_ERR) { int n; repeat(FILE_LINES) { int n = Random(0xFF); s = NumToStr(n); WriteLnString(handle,s,bytesWritten); } CloseFile(handle); } } task main() { byte handle; int fsize; string buf; bool eof = false; CreateRandomFile("rand.txt",FILE_LINES); if(OpenFileRead("rand.txt", fsize, handle) == NO_ERR) { TextOut(10,LCD_LINE2,"Filesize:"); NumOut(65,LCD_LINE2,fsize); Wait(600); until (eof == true) // read the text file till the end { if(ReadLnString(handle,buf) != NO_ERR) eof = true; ClearScreen(); TextOut(20,LCD_LINE3,buf); Wait(500); }
  • 47. 47 } CloseFile(handle); } No último programa, vou mostrar-lhe como ler números a partir de um arquivo. Aproveito a ocasião para vos dar uma pequena amostra de compilação condicional. No iníciodo código, existe um definição que não seja utilizado para uma macro nem para um alias: nós simplesmente definir INT. Depois, há uma declaração preprocessador #ifdef INT …Code… #endif que simplesmente diz ao compilador para compilar o código entre as duas afirmações se INT como foi previamente definido. Então, se nós definimos INT, a tarefa principal no interior do primeiro casal será compilado e se LONGO é definido, em vez de INT, a segunda versão do principal será compilado. Este método permite-me mostrar em um único programa tanto como int (16 bits) e longo (32 bits) tipos podem ser lidos a partir do arquivo chamando a mesma função ReadLn (handle, val). Tal como antes, ele aceita um arquivo punho e uma variável numérica como argumentos, retornando um código de erro. A função irá ler 2 bytes do arquivo, se passou a variável é declarada como int, e vai ler 4 bytes se o variável é longo. Bool variáveis também podem ser escritos e lidos da mesma forma. #define INT // INT or LONG #ifdef INT task main () { byte handle, time = 0; int n, fsize,len, i; int in; DeleteFile("int.txt"); CreateFile("int.txt",4096,handle); for (int i = 1000; i<=10000; i+=1000) { WriteLn(handle,i); } CloseFile(handle); OpenFileRead("int.txt",fsize,handle); until (ReadLn(handle,in)!=NO_ERR) { ClearScreen(); NumOut(30,LCD_LINE5,in); Wait(500); } CloseFile(handle); } #endif #ifdef LONG task main () { byte handle, time = 0; int n, fsize,len, i; long in; DeleteFile("long.txt"); CreateFile("long.txt",4096,handle); for (long i = 100000; i<=1000000; i+=50000) { WriteLn(handle,i);
  • 48. 48 } CloseFile(handle); OpenFileRead("long.txt",fsize,handle); until (ReadLn(handle,in)!=NO_ERR) { ClearScreen(); NumOut(30,LCD_LINE5,in); Wait(500); } CloseFile(handle); } #endif Resumo Neste último capítulo que preenchidas as avançadas funcionalidades oferecidas pela NXT: alta resolução timer, matricial e visor filesystem. 13. Observações finais Se você trabalhou o seu caminho através deste tutorial você pode agora considerar bastante especialista em NXC. Se não tiver feito isso, até agora, é tempo para começar a experimentar sozinho. Com criatividade em design e programação você pode tornar robôs Lego fazer coisas inacreditáveis. Este tutorial não cobrem todos os aspectos da BricxCC. Está recomendado a leitura do Guia NXC em cada capítulo. Além disso, NXC ainda está em desenvolvimento, a versão futura poderia incorporar funcionalidade adicional. Muitos conceitos de programação, não foram tratados neste tutorial. Em particular, nós não consideramos comportamento de aprendizagem robôs ou outros aspectos da inteligência artificial. Também é possível conduzir um robô Lego diretamente de um PC. Isto requer que você para escrever um programa em uma linguagem como C + +, Visual Basic, Java ou Delphi. Também é possível deixar que um tal programa trabalhará em conjunto com um NXC programa em execução no NXT si. Essa combinação é muito poderoso. Se você estiver interessado nesta forma de programação do seu robot, melhor começar com o download do SDK Fantom e Open Source documentos da NXTreme secção de Lego Mindstorms site. http://mindstorms.lego.com/Overview/NXTreme.aspx A web é uma fonte perfeita para informações adicionais. Alguns outros pontos importantes são sobre LUGNET, a LEGO Users Group Network (não oficial): http://www.lugnet.com/robotics/nxt