Advertisement
Guest User

Untitled

a guest
Dec 8th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.64 KB | None | 0 0
  1. Relatório da Parte 2 do Projeto | Grupo 20
  2. Escolhas para as representações
  3. Neste projeto, apesar do seu desenvolvimento ser, de um modo geral, bastante linear, existem alguns detalhes que podem variar consoante a preferência de cada um. São exemplos disso a duração do temporizador e a duração de um ciclo, que definimos como sendo 1/10s e 1/8s, respetivamente, por recomendação do professor. Isto significa que a cada 1/10s (a duração do timer), a posição do objeto vai atualizar o equivalente a 1/8s de movimento. Achamos que eram valores apropriados, uma vez que são valores próximos, e isso significa que o movimento da bola vai ser uma representação próxima da realidade, e o uso de 1/8s para a duração do ciclo (Δ𝑡), que pode ser representado em base 2 (2-3), facilita os cálculos que são feitos ao longo do programa e reduz o erro que estes possuem. Os nossos valores são representados em vírgula fixa, em formato Q10.6, ou seja, dos 16 bits existentes em cada palavra, os 6 menos significativos correspondem à parte fracional do número, e os restantes 10 correspondem à parte inteira. Como usamos complemento para 2 para representar valores negativos, o bit mais significativo representa o sinal do número. Consideramos ainda a aceleração gravítica como 10, representada no formato Q0, que permite uma representação mais simples e, mais uma vez, simplifica os cálculos feitos ao longo do programa.
  4. Funcionamento do programa
  5. Assim que o programa inicia, a stack é inicializada, as interrupções são ativadas, e a base do gráfico é escrita no terminal. Entende-se por base do gráfico a primeira e última linha compostas por 80 asteriscos, e a 2ª linha composta por um asterisco em cada extremidade. O gráfico é escrito a partir de 2 funções semelhantes, escrita e escrita2. A primeira escreve a linha superior e inferior, a segunda é responsável pela 2ª linha.
  6. De seguida, o ciclo principal inicia o temporizador e corre as 5 rotinas principais do nosso código: posicao, limite_pos, aceleracao, velocidade e desenha_bola, pela ordem referida.
  7. A função posicao, que se manteve inalterada em relação à parte 1 do projeto, recebe pAtual, correspondente à posição anterior e devolve a posição (coloca o novo valor em pAtual) após o movimento, segundo a função 𝑃𝐴𝑡𝑢𝑎𝑙=𝑃𝐴𝑛𝑡𝑒𝑟𝑖𝑜𝑟+𝑉𝐴𝑡𝑢𝑎𝑙×Δ𝑡.
  8. Após calcular a nova posição, é necessário verificar se atingiu algum dos limites, uma vez que a posição tem de estar sempre entre 1 e 78, inclusive. Sempre que a função atinge um dos limites, ressalta e continua o seu movimento na direção oposta, com velocidade equivalente ao simétrico da sua velocidade antes do ressalto. Para isto, recorremos à função limite_pos. Esta função começa por verificar se a posição atual é superior a 78, e, caso seja, obtém a diferença e retira-a a 78. Isto é, se a posição atual for 78+𝑥, a função devolve 78−𝑥. Caso não tenha atingido o limite superior, a função verifica se passou o limite inferior, 1. Isto é feito de forma semelhante ao limite superior, mas possui uma exceção. O valor é tratado de maneira diferente se for menor que 0 ou se tiver entre 0 e 1.
  9. Quando o valor é inferior ou igual a 0, obtém-se o seu simétrico e soma-se a 1, ou seja, para uma posição atual 𝑥, com 𝑥<0 , a função devolve o valor 1+(−𝑥). Quando temos uma posição atual 𝑥, com 0<𝑥<1, a função devolve a soma de 1 com a distância percorrida após passar o limite, isto é, (1−𝑥)+1. Após calcular as novas posições, estas são guardadas em pAtual, e como houve um ressalto, obtém-se a velocidade atual e coloca-se o seu simétrico em vAtual. Caso nenhum dos limites seja ultrapassado, a função limite_pos não faz nada.
  10. Após o cálculo da nova posição, é necessário calcular a velocidade que será responsável pelo movimento seguinte. Para isto, é necessário calcular a aceleração do objeto. Assim, é chamada a função aceleracao, que começa por ler o valor da aceleração da placa (𝑎), aplicando-lhe a fórmula 𝑎÷256×𝑔, com 𝑔, correspondente ao valor da aceleração gravítica, obtido da constante acelg.
  11. Na verdade, no nosso programa, apenas dividimos o valor da aceleração por 4. Isto deve-se ao facto do valor lido vir no formato Q0, isto é, devido à representação em vírgula fixa que utilizamos (Q6), o valor da aceleração da placa corresponde a 1/64 (2-6) do seu valor real. Assim, para obtermos 𝑎÷256, necessitamos apenas de dividir o valor lido por 4. A multiplicação de 𝑎÷256 por 𝑔 é feita através de uma função auxiliar multiplicar, que é baseada na função de multiplicação que nos foi fornecida na aula de laboratório. Como estamos a trabalhar com vírgula fixa, o produto de quaisquer 2 valores vem no formato Q𝑥, com 𝑥 correspondente à soma do número de bits reservados às casas decimais de cada um dos operandos. Como foi explicado anteriormente, 𝑎÷256 está representado no formato Q6, e como é referido no início deste relatório, a aceleração gravítica, 𝑔, encontra-se no formato Q0. Assim, desta multiplicação obtemos um valor para a aceleração atual em Q6, que é guardada na variável acel.
  12. Com a aceleração calculada, resta-nos um último cálculo, a velocidade que será utilizada no próximo movimento. À semelhança de posicao, a função velocidade também se manteve inalterada da 1ª parte do projeto. Esta função recebe o valor da velocidade utilizada no ciclo anterior, e, com base na aceleração do objeto, calcula, segundo a fórmula 𝑉𝐴𝑡𝑢𝑎𝑙=𝑉𝑎𝑛𝑡𝑒𝑟𝑖𝑜𝑟+𝑎×Δ𝑡, o valor que o objeto terá para a velocidade no ciclo seguinte.
  13. Finalmente, após os cálculos estarem concluídos, resta apenas atualizar a posição da bola no terminal. Isto é feito recorrendo à função desenha_bola. Esta função começa por limpar todos as posições possíveis para a bola através da função limpa_linha2, isto é, na 2ª linha coloca um espaço livre em todas as posições de 1 a 78. De seguida, obtém a parte inteira do valor da posição, isto é, passa do formato Q6 para Q0, e coloca a bola na posição correspondente.
  14. Após todos os cálculos e a atualização da posição da bola no terminal, o programa entra no ciclo check_timer, onde verifica se o registo R4 contém o valor 0. Esta verificação deve-se ao facto de que quando ocorre uma interrupção do temporizador, o registo R4 passa a conter o valor 0. Quando isto ocorre e a função check_timer verifica que o valor em R4 é, de facto, 0, volta ao início da função main, onde o valor de R4 é definido como 1. Este registo, ao longo do programa, é usado exclusivamente para este propósito, por forma a não perturbar o funcionamento do temporizador.
  15. Escolhemos este método de verificar se o temporizador já tinha terminado, uma vez que a alternativa seria um ciclo que lia a variável TIMER_STATUS. No entanto, por ter de aceder à memória para poder ler esse valor, seria um processo mais demorado, e, por isso, menos eficiente.
  16. Assim, a partir do momento em que é iniciado, o programa inicia este ciclo, e verificamos uma atualização da posição da bola no terminal a cada 0.1s, como previsto.
  17. Nota: Enquanto testávamos o projeto, tivemos alguns problemas com o simulador pois o nosso programa não funcionava como devido, tanto no browser como no executável. No entanto, quando experimentamos num dispositivo diferente com um browser diferente, o programa funcionou sem qualquer problema. Mesmo após inúmeras revisões ao código, não conseguimos concluir qual era o erro, por isso assumimos como sendo um erro do simulador.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement