Usar função cos no CCS C

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Usar função cos no CCS C

Mensagempor RAguiar » 21 Ago 2011 14:22

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]
Paciência é tudo.
RAguiar
Byte
 
Mensagens: 164
Registrado em: 17 Jun 2010 12:52
Localização: Louveira/SP

Re: Usar função cos no CCS C

Mensagempor andre_luis » 21 Ago 2011 15:00

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 )


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Usar função cos no CCS C

Mensagempor RAguiar » 21 Ago 2011 15:11

andre_teprom escreveu: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 )


+++


Olá André.


tipo assim?:

e = cos (73);
f = (e * 3,14)/360

?
Obrigado
Paciência é tudo.
RAguiar
Byte
 
Mensagens: 164
Registrado em: 17 Jun 2010 12:52
Localização: Louveira/SP

Mensagempor Jorge_Francisco » 21 Ago 2011 15:43

graus = 73
radiano = graus * 3.1416 / 180

f = cos(radiano)
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor RAguiar » 21 Ago 2011 16:03

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!
Paciência é tudo.
RAguiar
Byte
 
Mensagens: 164
Registrado em: 17 Jun 2010 12:52
Localização: Louveira/SP

Mensagempor andre_luis » 21 Ago 2011 16:08

Porque não usa tabela, ao invez de função ?

+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor RAguiar » 21 Ago 2011 16:15

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.
Paciência é tudo.
RAguiar
Byte
 
Mensagens: 164
Registrado em: 17 Jun 2010 12:52
Localização: Louveira/SP

Mensagempor andre_luis » 21 Ago 2011 16:42

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 ;
      }
}


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor RAguiar » 21 Ago 2011 16:51

...me desculpe cara, mas ainda vai faltar muito pra mim chegar no seu nível...
:lol:
Paciência é tudo.
RAguiar
Byte
 
Mensagens: 164
Registrado em: 17 Jun 2010 12:52
Localização: Louveira/SP

Mensagempor andre_luis » 21 Ago 2011 21:51

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.

+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor MOR_AL » 22 Ago 2011 11:26

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
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor Fabio777 » 22 Ago 2011 13:18

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
Fabio777
Nibble
 
Mensagens: 62
Registrado em: 19 Fev 2008 11:26


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x