Usar função cos no CCS C

Enviado:
21 Ago 2011 14:22
por RAguiar
Olá pessoal.
...segue um trecho do programa:
#include <16f628a.h>
#use delay (clock=4000000)
#fuses INTRC_IO, NOWDT, NOPUT, NOMCLR, NOBROWNOUT
#byte porta = 0x05
#byte portb = 0x06
#include "lcd.c"
#include "math.h"
void main()
{
While(true)
{
int16 b;
int32 c;
float d, e;
...
e = cos (73); [/b]
lcd_putc ("\f");
printf (lcd_putc, "FP = %f\r\n", e);
}...
...o valor à mostrar no display deveria ser "0,29", mas aparece "-0,73"...pois cosseno de 73 é 0,29.
...já experimentei trocar %f por %u, %lu, %e e outros, mas não aparece o resultado que deveria.
???[/b]
Re: Usar função cos no CCS C

Enviado:
21 Ago 2011 15:00
por andre_luis
RAguiar,
O resultado está certo, pois a função Coseno aplica um argumento em RADIANO e não em GRAU.
Utilize a calculadora do Windows para confirmar.
Aplique uma formula de conversão do argumento do tipo :
Ang|rad| = Ang|grad| * ( ( 2 * PI ) / 360 )
+++

Enviado:
21 Ago 2011 15:43
por Jorge_Francisco
graus = 73
radiano = graus * 3.1416 / 180
f = cos(radiano)

Enviado:
21 Ago 2011 16:03
por RAguiar
Jorge_Francisco escreveu:graus = 73
radiano = graus * 3.1416 / 180
f = cos(radiano)
valeu cara, deu certo aqui...
...po meu, toda hora eu tenho que mudar alguma coisa no programa ou no hardware, agora apareceu mais um problema, além do codigo acima, tem mais algumas linhas (pouca coisa) e a memória ROM do 16f628A acabou (consumiu + uns 40% quando inclui o #include "math.h")...vou ter de migrar de pic.
Vlw!

Enviado:
21 Ago 2011 16:08
por andre_luis
Porque não usa tabela, ao invez de função ?
+++

Enviado:
21 Ago 2011 16:15
por RAguiar
andre_teprom escreveu:Porque não usa tabela, ao invez de função ?
+++
como seria essa tabela André?
...eu tentei usar uma artimanha para não usar o #include "math.h"...mas acabou ocupando o mesmo espaço (ROM) ou até mais...
...aí que é F***, usar um PIC desse só para medir um tempo, passar para graus e cosseno e mostar no display...futuramente isso irá medir em cada fase de um sistema trifásico, com essas limitações de memória vou ter de pesquisar o uso de outro tipo de microcontrolador...ou uma expanção da ROM.

Enviado:
21 Ago 2011 16:42
por andre_luis
Segue um trecho do programa que fiz para um UPS.
Nesse caso, uma resolução de 1/32 por ciclo já era suficiente.
- Código: Selecionar todos
////////////////////////////////////////////////////////////////////////
const unsigned int8 Duty0 [] = {7,15,23,31,38,46,53,61,68,75,82,88,95,101,107,113,118,123,128,133,137,141,144,147,150,153,155,156,158,159,159,160}; // 126 Vac@24Vdc
const unsigned int8 Duty1 [] = {7,15,23,30,38,45,52,60,67,74,80,87,93,99,105,111,116,121,126,130,134,138,142,145,148,150,152,154,155,156,157,157};
.......
const unsigned int8 Duty30 [] = {5,10,15,20,25,30,35,40,44,49,54,58,62,66,70,74,77,81,84,87,90,92,95,97,99,100,102,103,104,104,105,105}; // 117Vac@18Vdc
const unsigned int8 Duty31 [] = {5,10,15,20,25,30,35,39,44,49,53,57,61,65,69,73,77,80,83,86,89,91,94,96,97,99,100,102,102,103,103,104};
const unsigned int8 Duty32 [] = {5,10,15,20,24,29,34,39,43,48,52,57,61,65,69,72,76,79,82,85,88,90,92,95,96,98,99,100,101,102,102,102};
////////////////////////////////////////////////////////////////////////
void CarregaPWM ( void )
{
if ( direcao == CRESCENTE ) PWM_counter++ ;
else PWM_counter-- ;
switch ( PWM_counter )
{
case 0 : NivelMinimo() ; set_pwm1_duty ( 0 ) ; break ;
case 1 : set_pwm1_duty ( Duty[PWM_counter] ) ; break ;
case 2 : set_pwm1_duty ( Duty[PWM_counter] ) ; break ;
..........
case 29 : set_pwm1_duty ( Duty[PWM_counter] ) ; break ;
case 30 : set_pwm1_duty ( Duty[PWM_counter] ) ; break ;
case 31 : NivelMaximo() ; set_pwm1_duty ( Duty[PWM_counter] ) ; break ;
}
}
+++

Enviado:
21 Ago 2011 16:51
por RAguiar
...me desculpe cara, mas ainda vai faltar muito pra mim chegar no seu nível...


Enviado:
21 Ago 2011 21:51
por andre_luis
RAguiar escreveu:...mas ainda vai faltar muito pra mim chegar no seu nível...
Desculpa, eu não queria te assustar, mas não há complexidade nessa abordagem.
Trata-se apenas de um mapeamento de uma função em intervalos finitos.
+++

Enviado:
22 Ago 2011 11:26
por MOR_AL
RAguiar.
Você pode reduzir a quantidade de memória.
Vamos considerar que você queira resolução de 1º no eixo dos tempos (x) e resolução de 1/255 para o valor da sua função (y), que no caso é coseno.
1 - Determine o início de cada semiciclo, de sua fase que está sendo monitorada, e se ele é positivo ou negativo.
Use um circuito que tem de montão na net.
2 - Use um contador do PIC para gerar uma interrupção a cada grau (T1grau = 1.000.000/(60*360), em us).
3 - Divida o ciclo da senóide de sua rede (o fio fase) em 4 intervalos. De 0º a 89º, de 90º a 179º, de 180º a 269º e de 270º a 359º. Repare que, em termos de valores do coseno, você precisa de uma tabela com apenas 90 valores (um por grau de 0º a 89º). Os valores do segundo intervalo são iguais aos do primeiro, apenas trocando o sentido de leitura dos dados do primeiro.
Os valores do terceiro intervalo são iguais aos do primeiro, apenas trocando o sinal. Os valores do quarto são iguais aos do primeiro, trocando-se tanto o sinal como o sentido de leitura da tabela. Com isso você reduz o tamanho de sua tabela em 4 vezes.
Crie uma variável que determina a contagem dos graus do contador. Essa variável vai contar de 0 a 90. Para isso você precisa dos 7 bits menos significativos dessa variável. Você precisará de 2 flags. Estes flags informam o valor do semi-ciclo, se 1, 2, 3 ou 4.
Essa informação será necessária para identificar o valor na sua tabela, sentido de leitura e o sinal para isso.
Cada valor de sua tabela será proporcional ao valor de seu registro.
Os valores da tabela serão:
y(n) = 255*seno(n * pi/180). Os valores de n serão 0, 1, 2, 3, ..., 88, 89, 90. (sua tabela terá 91 valores, sendo que o menor é zero e o maior é 255).
4 – Evite os limites de ângulos, que se situam junto às transições. 359º com 0º, 89º com 90º, 179º com 180º e 269º com 270º. Qualquer ruído na sua senóide da rede ou qualquer pequeno erro no seu contador, pode fazer pular de um pedaço de semi-ciclo para outro.
Fazendo isso, e se for somente isso, você evita aritmética de ponto flutuante e até de inteiro com dois bytes.
MOR_AL

Enviado:
22 Ago 2011 13:18
por Fabio777
Também da pra utilizar série de Taylor
Para cossenos em radianos com o X tendendo à zero:
f(x) = 1 - (x^2)/2
Ai vc pode melhorar a resolução se continuar a série.
Ouvi falar que algumas calculadoras utilizam este calculo em senos e cossenos