Página 1 de 2

Como gerar PWM no Delphi ?

MensagemEnviado: 03 Set 2011 09:32
por cellostec
Olá amigos. Não estou conseguindo gerar uma saída PWM pelo Delphi. Tenho um programa host que envia dados via USB para um protótipo microcontrolado. Um comando ativa uma saída do dispositivo, outro comando desativa. Esta saída controla um motor 12 v.
Tentei o comando sleep dentro de um timer, sem sucesso. Até funciona mas aos trancos. O motor não tem um controle linear. Fiz assim:

procedure ttimer.ontimer;
begin
ligamotor;
sleep(5);
paramotor;
sleep(5);
end;

O timer setado em 10ms. Fiz inúmeras tentativas com valores diversos no
comando sleep e set do timer.
Utilizei uma rotina Delay utilizando o GetTickCount para substituir o sleep, mas também sem sucesso.
Alguém tem alguma dica ? Desde já agradeço. :D
Fernando Barcellos

Re: Como gerar PWM no Delphi ?

MensagemEnviado: 03 Set 2011 10:40
por andre_luis
Fernando,


Programas executados em sistemas operacionais não-preemptivos como o Windows, possuem uma alocação de thread variável. Por isso, uma temporização numa base de tempo tão pequena ( 5ms ), será imperceptível diante do atrazo de inúmeros processos.

Uma alternativa que adotei num projeto específico e que funcionou muito bem, foi a utilização de um hardware externo com temporização baseado em Cristal, para gerar interrupção IRQ, que tem prioridade de execução, e assim eu garantia um tratamento imediato.

Apenas para elucidar o meu caso ( simulador de ECG ) :
Placa Externa : Envia pela UART, um byte na TX numa cadencia fixa de exatos 240Hz ( 4,1666ms )
PC : Programa feito em C++Builder, que ao receber no RX um byte de comando da placa pela serial, gera uma interrupção que o faz o PC devolver á essa placa uma das amostras do sinal da BD a ser convertido no D/A da placa.

Antes dessa abordagem, o sinal na placa era apresentado fora da frequencia correta, com muitas distorções, provenientes dos pequenos "travamentos" natural do Windows.


+++

MensagemEnviado: 03 Set 2011 11:28
por cellostec
Eu suspeitei que o problema fosse o próprio PC-Windows-Delphi.
Ainda tenho a alternativa de implementar o PMW no próprio 18F4550 ou até utilizar um hardware (Ex: ci 555) externo ao PIC.
Estou desenvolvendo um robozinho doméstico controlado pelo Netbook e ainda vou utilizar muitas rotinas temporizadas (todas sujeitas a interferência de uma com outra - então quanto menos melhor).
Valeu André! :D

Fernando Barcellos

Re: Como gerar PWM no Delphi ?

MensagemEnviado: 03 Set 2011 11:35
por Red Neck Guy
andre_teprom escreveu:Fernando,

....sistemas operacionais não-preemptivos como o Windows..

+++


O windows desde o 95 é preemptivo....

MensagemEnviado: 03 Set 2011 11:45
por cellostec
Eis meu robozinho, antes da interface USB. Ainda utilizava a LPT.

Imagem

MensagemEnviado: 03 Set 2011 12:52
por vtrx
///////////////////////////////////////////////////////////////

MensagemEnviado: 03 Set 2011 12:52
por vtrx
Um dos erros de sua rotina é que esta faltando 'application.processmessages' antes dos 'Sleep'.

MensagemEnviado: 03 Set 2011 18:37
por cellostec
Utilizei a seguinte procedure para substituir o sleep:

procedure TfrmMenu.Delay(MSec: Cardinal);
var
Start: Cardinal;
begin
Start := GetTickCount;
repeat
Application.ProcessMessages;
until (GetTickCount - Start) >= MSec;
end;

Aí, até funcionou, mas não consegui valores de tempo que fizessem os motores trabalharem de forma linear (sem trancos). :cry:

Fernando Barcellos

MensagemEnviado: 03 Set 2011 18:48
por andre_luis
Fernando,

Procura por SetPriorityClass.
Pode ser que executando o programa com um nível de prioridade maior, o problema seja reduzido.


+++

MensagemEnviado: 03 Set 2011 19:54
por vtrx
Use esta rotina que é de tempos mais precisos e pode ter intervalos menores que 1 milissegundo.
Código: Selecionar todos
procedure MicroDelay;
var
  hrRes, hrT1, hrT2, dif: Int64;
begin
  if QueryPerformanceFrequency(hrRes) then
  begin
    QueryPerformanceCounter(hrT1);
    repeat
      QueryPerformanceCounter(hrT2);
      dif := (hrT2 - hrT1) * 10000000 div hrRes;
   until dif > TempoDelay;
  end;

end;

Onde 'TempoDelay' é um Integer.
Use 850 para TempoDelay,para voce ter uma referencia.
Faltou voce citar se está usando USB e qual classe ta usando,caso seja HID,só terá intervalos mínimos de 1 milissegundo.

MensagemEnviado: 14 Set 2011 19:50
por cellostec
André:
Defini meu aplicativo como prioridade alta mas não resolveu. Tentei até tempo real (apesar do computador enlouquecer) mas também não adiantou.
Vtrx:
A rotina de microdelay que tu sugeriu minimizou bastante os trancos mas eles ainda existem. A interface USB é sim pelo modo HID.

Hoje desliguei um dos motores e liguei outro no lugar. Funcionou beleza.
Então desconfio que seja a redução ( do tipo rosca sem fim acionando uma engrenagem - motor para vidros elétricos de automóveis). Este conjunto motor-redução quando não ativado, trava.
Abaixo o motor que estou utilizando:

Imagem

Motores para acionamento de vidros de carros

MensagemEnviado: 15 Mar 2012 11:53
por malereis
Olá amigo.
Esses motores que está usando são fabricados da pior forma possível.
Não são precisos, são cheios de folgas e vc vai ter problemas de travamento.
Use motores de passo que é melhor.

Abraços

MensagemEnviado: 15 Mar 2012 13:05
por cellostec
O problema mareleis aí é o custo. Indiscutivelmente o motor de passo é superior mas com a potência que preciso para tocar o robô o preço fica fora de questão. Substituí os motores para vidros por motores de parafusadeira (com redução tipo orbital). Ficou bom e aceita bem PWM.

RGB

MensagemEnviado: 15 Mar 2012 18:22
por malereis
Olá Cellostec.

Estamos trocando idéias e de repente acho que vc tem a solução que busco.

Veja se pode ajudar.
Preciso programar um pic que tenha acesso RS232 (alguns não).
O programa precisa, segundo me passaram, trabalhar com PWM para acender um LED RGB - 3 cores.

O problema é que nao sou muito bom ainda com Pics e estou arrancando os cabelos (os que sobraram hehe).
No delphi, até que dou minhas cacetadas, mas no Pic não sei como fazer isso.

Esse Pic vou ter que fazer conversar com o Delphi para esse efeito. (mudar as cores via código pelo Delphi).
Uma vez o pic programado, tenho aqui um componente para RS232 que comprei em um site russo e funciona bem a beça no Delphi com o PIC.

Veja este vídeo.
Se puder ajudar, te agradeço e se precisar de algo em mecanica ou um pouco de Delphi, pode escrever.

http://www.youtube.com/watch?v=eRKSGl-31iI

MensagemEnviado: 18 Mar 2012 09:30
por cellostec
Olá malereis:
O que tu queres fazer é perfeitamente possível e não é muito difícil. Dá inclusive para fazer de mais de uma forma. Então a abordagem inicial acho que seria qual a melhor pelo custo x benefício.
Vais precisar de um modelo de PIC que tenha comunicação RS232 e gere
PWM.
- RS232 : nunca utilizei. Quando iniciei (recentemente) estudos de comunicação do PC com o PIC já não tinha mais porta serial, de forma que me atraquei com a USB. Mas acho que a maioria dos PICs (todos que conheço) é possível estabelecer a ligação.
- PWM : vais precisar de 3 canais para este projeto.Neste link: https://sites.google.com/site/sitexlipe ... otao-e-led tem um cara que fez com 2 canais. Vale dar uma olhada.
É possível também tu criares o PWM utilizando os timers do PIC.
Se tu emular o PWM e quiseres a RS232 um PIC16F628a dá conta.
Se quiseres PWM já prontinho e USB aí parte para o 18F4550.
Estou namorando este projeto já algum tempo pois gostaria de construir um detector de cores para meu robô. Montei um utilizando LDRs atrás de lentes coloridas mas não deu muito certo.
Como já estamos fugindo um pouco do tópico posta direto para:
cellostec@yahoo.com.br
Fernando Barcellos