×
Ir ao conteúdo
  • Cadastre-se

Arduino Controle PID em lampada (temperatura) com arduino


Posts recomendados

Eai pessoal,

 

Estou montando uma pequena estufa, gostaria de controlar e temperatura da mesma utilizando uma lampada no centro dela, para isto estou usando um módulo de controle de potencia AC, um arduino e um sensor LM35. 

 

Vamos ao problema... Inicialmente testei o módulo isoladamente (sem controle) apenas regulando o setpoint por um potenciometro, até aqui ocorreu tudo ok, a luminosidade é regulada perfeitamente, porém a ideia é regular a temperatura e nao a luminosidade, por isso resolvi incluir um controlador PID em um arduino, e aqui começaram os problemas, desenvolvi o código que está abaixo e realmente nao sei o que pode estar ocorrendo, pois o arduino trava com este código a ponto de nem mesmo a serial funcionar mais. Lembrando que ja utilizei este codigo anteriormente para controlar um motor, e funcionou... porém algo esta me escapando.

 

Se alguem puder dar uma segunda opiniao agradeço.

 

Segue código

 

#define PINO_ZC   2
#define PINO_DIM  9
#define PINO_LM35 A0
#define N         20


volatile long lum;

double error = 0,
       lastRPM;

double kP = 0.5,
       kI = 0.5, 
       kD = 0;
int controlSignal = 0;

double P = 0,                 //Proporcional
       I = 0,                 //integral
       D = 0,                 //derivativa
       PID;               //soma P+I+D
float SetPoint = 50;       //Alterar aqui o setpoint
       
float lastProcess = 0,
      deltaTime = 0;
     

void ZeroCross(){
  if(lum > 100) lum = 100;
  if(lum < 0) lum = 0;

  long t1 = 8200 * (100 - lum) / 100;
  delayMicroseconds(t1);
  digitalWrite(PINO_DIM, HIGH);
  delayMicroseconds(6);
  digitalWrite(PINO_DIM, LOW);
}

void setup() {
  pinMode(PINO_DIM, OUTPUT);
  pinMode(PINO_ZC, INPUT);
  pinMode(PINO_LM35, INPUT);

  Serial.begin(9600);
  attachInterrupt(0, ZeroCross, RISING);

}

float temp,
      temp2;

int original,
    filtrado;
    
int numbers[N];

    
void loop() {
  original = analogRead(PINO_LM35);                       //LE O VALOR DO SENSOR DE TEMPERATURA (0-1023)
  filtrado = MovingAverage();                             //CALCULA A TEMPERATURA FILTRADA
  temp = (float(filtrado)*5/(1023))/0.01;                 //TRANSOFORMA VALOR PARA TEMPERATURA (0-100)
  temp2 = (float(original)*5/(1023))/0.01;        


  error = SetPoint - temp2;                                //CALCULA O ERRO DO CICLO 
  
  float deltaTime = (millis() - lastProcess) / 1000.0;    //CALCULA O VALOR DO DELTA DE TEMPO E CONVERTE PRA SEGUNDOS
  lastProcess = millis();                                 //ARMAZENA O VALOR DO INSTANTE

  P = error*kP;                                           //CALCULA O VALOR DE P                                               
    
  I = I + (error*kI) * deltaTime;                         //CALCULA O VALOR DE I
  
  D = (lastRPM - temp2)*kD*deltaTime;                      //CALCULA O VALOR DE D
  lastRPM = temp2;

  PID = P + I + D;                                        //SOMA PID

  lum = map(PID, 0, 5000, 0, 85);
  //lum = PID;

  

  //Serial.println(temp);
  //Serial.print(" ");
  //Serial.println(temp2);
  Serial.print(lum);
  Serial.print(" ");
  Serial.println(temp2);
 
  delay(20);

  
}

long MovingAverage(){
  for(int i = N-1; i > 0; i--) numbers = numbers[i-1];

  numbers[0] = original;

  long acc = 0;

  for(int i = 0; i < N; i++) acc += numbers;

  return acc/N;
}


 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
5 horas atrás, toigogustavo disse:

o arduino trava com este código a ponto de nem mesmo a serial funcionar mais.

Acho que você deve localizar ONDE ele trava. Rode passo a passo, coloque break points, monitore algo pela serial pra ver até travar, etc ou algo do gênero

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Isadora Ferraz

Ontem fiz testes isoladamente, desativei a interrupção e mantive apenas a parte de PID ativa, e monitorei o sinal de controle da variável "PID" do código, para minha surpresta o sinal respondia conforme esperado, o sinal de controle aumenta na medida que a temperatura sobe, e reduz caso a temperatura aumente... Isto me leva a conclusao de que o problema está na interrupção da função ZeroCrossing() quando operada em conjunto com o PID. 

 

A partir deste ponto não fiz mais testes... porém é bem estranho a interrupção falhar isto ainda está fora do meu entendimento.

adicionado 3 minutos depois

Outra observação importante e que colabora com o que citei acima, é que o arduino "destrava" quando o módulo de potencia AC é desligado da rede, acredito eu que isto aconteça devido ao fato de que a interrupcao do código nao é mais chamada, pois nao havendo energia nao há detecção da passagem por zero.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Ele pode não estar conseguindo sair da interrupt ou sua variável t1 está assumindo um valor monstruoso pro delay, experimenta não deixar lum volatile. Outra ..costumo definir variáveis de tempo como unsigned afinal não existe tempo negativo...

+

Sua interrupt estar sendo chamada o tempo todo por ruídos. Filtre sua entrada com um capacitor xute 1...100nF ... ou achou que a vida é só soft?

 

Ah.. outra coisa... você usa delays fora e dentro da interrupt. Se a delay fizer uso da delayus ou usar os mesmos recursos de hw, pode dar "conflito de interesses"

 

bem.. é  Conclusão Hipotética Universal Técnica Explicativa kk

 

abç

  • Curtir 3
Link para o comentário
Compartilhar em outros sites

@Isadora Ferraz, parece que desta vez resolvi com software mesmo hehehe

 

Por curiosidade fui pesquisar sobre o tipo "volatile" na referencia do arduino, no seguinte link: https://www.arduino.cc/reference/pt/language/variables/variable-scope-qualifiers/volatile/

onde é recomendado que use breakpoints para evitar que a interrupção ocorra em determinado trexo do código, pois bem...

 

Inseri "noInterrupts()" ...código... "interrupts()" 

 

isto fez com que a interrupção não fosse chamada neste intervalo de operação, dando assim prioridade para esta operação, em resumo o valor da variavel global consultada pela funcao de interrupção agora esta sendo atualizado de forma correta em todos os ciclos, nao gerando mais problemas.

 

O PID funcionou perfeitamente, chega a zerar o erro bem rapidamente, ainda tem um problema de precisao por conta dos tipos de variaveis, mas isto é outra historia.

 

modifiquei o código da seguinte forma:

void loop() {
  original = analogRead(PINO_LM35);                       //LE O VALOR DO SENSOR DE TEMPERATURA (0-1023)
  filtrado = MovingAverage();                             //CALCULA A TEMPERATURA FILTRADA
  temp = (float(filtrado)*5/(1023))/0.01;                 //TRANSOFORMA VALOR PARA TEMPERATURA (0-100)
  temp2 = (float(original)*5/(1023))/0.01;        
  
  error = SetPoint - temp;                                //CALCULA O ERRO DO CICLO 
  
  float deltaTime = (millis() - lastProcess) / 1000.0;    //CALCULA O VALOR DO DELTA DE TEMPO E CONVERTE PRA SEGUNDOS
  lastProcess = millis();                                 //ARMAZENA O VALOR DO INSTANTE

  P = error*kP;                                           //CALCULA O VALOR DE P                                               
    
  I = I + (error*kI) * deltaTime;                         //CALCULA O VALOR DE I
  
  D = (lastRPM - temp)*kD*deltaTime;                      //CALCULA O VALOR DE D
  lastRPM = temp;

  PID = P + I + D;                                        //SOMA PID

  
 noInterrupts();
  lumm = map(PID, -10000, 10000, 0, 85);
  //lumm = PID*(85/4);
  
  //lum = PID;
  if(lumm < 4){
    lum = 4;
  }else{
    lum = lumm;
  }
  
  noInterrupts();
  if(lum > 85) lum = 85;
  interrupts();
 
  Serial.print(lum);
  Serial.print(" ");
  Serial.print(error);
  Serial.print(" ");
  Serial.print(PID);
  Serial.print(" ");
  Serial.println(temp);
 
  //delay(100);

  PID = 0;
  
}

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Bacana... o legal é que resolveu 'sozinho'. Mas mesmo assim, um 'evento' que este sistema deveria retornar é 'warning: missing magical words' ... bem pelo menos o meu (meu) 'compilador' daria este aviso...Mas enfim é só questão de valores mesmo...😑. Com o tempo você acerta eles ok?

ás, Isadora Ferraz disse:

... de nada ... de nada adiantou a mensagem subliminar kk... talvez nem esta kk

 

Boa sorte

Link para o comentário
Compartilhar em outros sites

2 horas atrás, Isadora Ferraz disse:

Mas mesmo assim, um 'evento' que este sistema deveria retornar é 'warning: missing magical words'

Pois é, porém parece que nao fui o unico com este problema, o colega neste forum tambem teve exatamente o mesmo problema: https://forum.arduino.cc/index.php?topic=243721.0

 

Mas em fim, resolvido!

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!