1
Programando Robôs
NXT
Usando NXC
(Beta 30 or higher)
(Version 2.2, June 7, 2007)
Por Daniele Benedettelli
Com Revisões d...
2
Prefácio
Tal como aconteceu para o bom e velho Mindstorms RIS, CyberMaster, e Spybotics,
para libertar todo o potencial ...
3
Sumário
Prefácio ..........................................................................................................
4
11. A comunicação entre robôs .............................................................................................
5
1. Gravando o seu primeiro programa
Neste capítulo vou mostrar-lhe como escrever um programa extremamente simples.
Estam...
6
A interface parece um editor de texto padrão, com o habitual menu e botões para
abrir e salvar arquivos, impressão arqui...
7
{
statement1;
statement2;
…
}
Nosso programa tem seis declarações. Olhemos para um deles no momento:
OnFwd(OUT_A, 75);
E...
8
Ao digitar nos programas, há uma hipótese razoável que você faça alguns erros.
Os avisos do compilador erros e relatá-lo...
9
Neste capítulo você escreveu seu primeiro programa no NXC, utilizando
BricxCC. Agora você deve saber qual o tipo de um p...
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ér...
11
#define MOVE_TIME 500
#define TURN_TIME 500
task main()
{
repeat(4)
{
OnFwd(OUT_AC, 75);
Wait(MOVE_TIME);
OnRev(OUT_C, ...
12
#define MOVE_TIME 500 // Time for a straight move
#define TURN_TIME 360 // Time for turning 90 degrees
task main()
{
re...
13
Variáveis forma um aspecto muito importante de todas as linguagens de
programação. As variáveis são locais na memória q...
14
task main()
{
aaa = 10;
bbb = 20 * 5;
ccc = bbb;
ccc /= aaa;
ccc -= 5;
aaa = 10 * (ccc + 3); // aaa is now equal to 80
...
15
Resumo
Neste capítulo você aprendeu sobre o uso de variáveis e matrizes. Você pode
declarar do que outros tipos de dado...
16
Nos capítulos anteriores vimos a repetir, e enquanto declarações. Estas
declarações controlar a forma como os outros de...
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...
18
pouco, adicionando um toque sensor. Tal como antes, siga as instruções para Tribot
construir o pára-choque dianteiro.
L...
19
Vamos agora tentar fazer o robô evitar obstáculos. Sempre que o robô atinge um
objeto, nós deixá-lo voltar um pouco, fa...
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 vir...
21
{
SetSensorSound(IN_2);
while(true)
{
until(MIC > THRESHOLD);
OnFwd(OUT_AC, 75);
Wait(300);
until(MIC > THRESHOLD);
Off...
22
Neste capítulo você viu como trabalhar com todos os sensores incluídos no NXT
set. Vimos também until e while comandos ...
23
Até agora todos os nossos programas consistiu de apenas uma tarefa. Mas NXC
programas podem ter múltiplas funções. É ta...
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...
25
OnFwd(OUT_AC, 75);
}
task main()
{
OnFwd(OUT_AC, 75);
Wait(1000);
turn_around();
Wait(2000);
turn_around();
Wait(1000);...
26
OnFwd(OUT_AB, 75);
Wait(1000);
turn_around;
Wait(2000);
turn_around;
Wait(1000);
turn_around;
Off(OUT_AB);
}
Após a dec...
27
O NXT tem um alto-falante que pode reproduzir tons e mesmo ficheiros de som.
Trata-se, em especial útil quando você que...
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...
29
Há um número adicional de motor comandos que você pode usar para controlar
os motores com mais precisão. Neste capítulo...
30
Wait(2000);
Off(OUT_AC);
PlayTone(4000,50);
Wait(1000);
ResetTachoCount(OUT_AC);
OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED);...
31
(that can be set to true or false). It also lets youspecify whether the motors should brake
after the angle of rotation...
32
(50,0,0): o motor não girar 180 °, exactamente, uma vez que um erro
continua descompensada
(0, x, x): sem a parte propo...
33
empurrado parcialmente o valor varia entre 50 e 1000. Portanto, se você definir um
sensor de toque modo raw você pode r...
34
A rotação é um sensor muito útil tipo de sensor: é um encoder óptico, quase
o mesmo que construir um dentro NXT servomo...
35
Um pouco de renúncia é necessária no início desta secção! Devido à nova
estrutura de melhores NXT sensores e 6 -- fios ...
36
{
SetSensorType(IN_1, SENSOR_TYPE_LIGHT);
SetSensorMode(IN_1, SENSOR_MODE_RAW);
while (true)
{
if ((SENSOR_1 < 100) || ...
37
OnFwd(OUT_C, 75);
}
}
}
task submain()
{
while (true)
{
OnFwd(OUT_AC, 75); Wait(1000);
OnRev(OUT_C, 75); Wait(500);
}
}...
38
}
O ponto crucial é que tanto o check_sensors e tarefas move_square podem
controlar motores apenas se nenhuma outra tar...
39
}
}
task main()
{
sem = 0;
Precedes(move_square, submain);
}
Você poderia argumentar que não é necessário em move_squar...
40
//MASTER
#define BT_CONN 1
#define INBOX 1
#define OUTBOX 5
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_ERR)...
41
Você irá notar que abortar um dos programas, os outros vão continuar a
enviar mensagens com crescente números, sem sabe...
42
//SLAVE
#define BT_CONN 1
#define OUT_MBOX 1
#define IN_MBOX 5
sub BTCheck(int conn)
{
if (!BluetoothStatus(conn)==NO_E...
43
}
Resumo
Neste capítulo, estudamos alguns dos aspectos básicos da comunicação
Bluetooth entre robôs: conectando dois NX...
44
OnFwd(OUT_AC, 75);
until ((SENSOR_1 == 1) || ((CurrentTick()-t3) > 10000));
Off(OUT_AC);
}
Não se esqueça que temporiza...
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-...
46
Realmente simples, este programa cria o arquivo e, se não ocorreu nenhum
erro, ele escreve um número de 0 a 255 (conver...
47
}
CloseFile(handle);
}
No último programa, vou mostrar-lhe como ler números a partir de um
arquivo.
Aproveito a ocasião...
48
}
CloseFile(handle);
OpenFileRead("long.txt",fsize,handle);
until (ReadLn(handle,in)!=NO_ERR)
{
ClearScreen();
NumOut(3...
Próximos SlideShares
Carregando em…5
×

Nxt Bricx

314 visualizações

Publicada em

Apostila das linhas de comando NXT usando Bricx.

Publicada em: Educação
0 comentários
1 gostou
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
314
No SlideShare
0
A partir de incorporações
0
Número de incorporações
4
Ações
Compartilhamentos
0
Downloads
7
Comentários
0
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Nxt Bricx

  1. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

×