Estou tentando controlar um fader motorizado (potenciômetro linear deslizante) usando um Arduino.
O controle PID fornece bons resultados para "pular" para uma posição-alvo específica, mas rastrear rampas é um problema, não é nada suave. O movimento é muito instável, não importa o que eu tente.
Aqui está um gráfico da posição de referência, da posição medida e da saída do motor ao rastrear uma rampa:
E aqui está um vídeo desse mesmo teste.
Em sistemas comerciais, parece muito mais suave, veja isso .
Detalhes :
O fader do motor é um RSA0N11M9A0K dos Alpes . Para controlá - lo, estou usando uma ponte H ST L293D , alimentada por uma fonte de alimentação regulada de 10 V DC ( XL6009 ).
No UNO do Arduino (ATmega328P), estou usando os pinos 9 e 10, com uma frequência PWM de 31.372 kHz para torná-lo inaudível (Timer1 com um pré-calibrador de 1,TCCR1B = (TCCR1B & 0b11111000) | 0b001
).
O potenciômetro é conectado entre o terra e 5V, com o limpador indo para ADC0, como de costume.
O controlador :
estou usando um controlador PID simples com anti-corda, que é atualizado a uma taxa de 1 kHz (Ts = 1e-3 s):
float update(int16_t input) {
int16_t error = setpoint - input;
int16_t newIntegral = integral + error;
float output = k_p * error
+ k_i * newIntegral * Ts
+ k_d * (input - previousInput) / Ts;
if (output > maxOutput)
output = maxOutput;
else if (output < -maxOutput)
output = -maxOutput;
else
integral = newIntegral;
previousInput = input;
return output;
}
A saída do controlador é um valor de -127 a 127. A saída PWM é gerada da seguinte maneira:
const int8_t knee = 48;
uint8_t activation(int8_t val) {
if (val == 0)
return 0;
else {
return map(val, 0, 127, 2 * knee, 255);
}
}
void writeMotor(int8_t val) {
if (val >= 0) {
analogWrite(forward, activation(val));
digitalWrite(backward, 0);
} else {
analogWrite(backward, activation(-val));
digitalWrite(forward, 0);
}
}
Adicionei 48 ao sinal PWM de 7 bits, porque é aí que o motor começa a se mover a 31 kHz e, em seguida, escalono-o para um número de 8 bits (porque é isso que a analogWrite
função espera):
O que eu tentei :
tentei adicionar um filtro EMA à entrada, ao sinal de controle e ao componente derivado do controlador PID, mas sem sucesso. Também tentei abaixar a resolução da entrada analógica, usando a histerese para impedir que ela alternasse entre dois valores quando estacionária. Isso não parece afetar nada. Aumentar o tempo para 10 ms também não parece ajudar.
Também tentei fazer uma identificação do sistema no MATLAB e tentei ajustá-lo no Simulink (seguindo este série de vídeos ). Consegui um modelo com um ajuste de 91%, mas não sabia como lidar com as não linearidades de entrada e saída do modelo MATLAB, como elas afetam o ajuste do PID e como implementá-lo no Arduino.
A última coisa que tentei é fazer dois controladores diferentes: um para grandes saltos na posição de referência e outro para pequenos erros ao rastrear uma rampa. Isso parece ajudar um pouco, porque então eu posso aumentar o coeficiente integral no rastreamento, sem aumentar o overshoot ao pular.
No entanto, aumentando o ganho integral (e proporcional), o motor agora está sempre fazendo alguma coisa, mesmo quando deve estar parado e a referência não muda. (Ele realmente não se move, mas você pode senti-lo vibrando.)
Não tenho praticamente nenhum ganho derivativo, porque aumentá-lo acima de 1e-4 parece torná-lo ainda mais instável e não percebo nenhuma diferença entre 0 e 1e-4.
Meu palpite é que ele precisa de mais energia para superar o atrito estático, então o atrito dinâmico é menor, então ele ultrapassa, então aciona o motor para trás, fazendo com que ele pare novamente, então ele precisa superar o atrito estático novamente, dispara para a frente novamente , etc.
Como os controladores comerciais superam esse problema?
Minha formação :
estou no meu terceiro ano de bacharelado em engenharia elétrica, segui cursos de teoria de controle, processamento de sinal digital, controle LQR etc., por isso tenho alguma formação teórica, mas estou tendo problemas para aplicar todas essas este sistema do mundo real.
Edit :
Eu testei as medições do sensor de malha aberta, como o laptop2d recomendou, e estou bastante surpreso com os resultados: Em altas frequências PWM, existem picos desagradáveis nas leituras. Em 490 Hz, não há nenhum.
E isso está em um ciclo de trabalho constante, então não consigo imaginar que tipo de ruído recebo quando o motor está invertendo a direção muito rapidamente.
Portanto, terei que encontrar uma maneira de filtrar esse ruído antes de começar a trabalhar no controlador novamente.
Edit 2 :
Usar um filtro de média móvel exponencial não foi suficiente para filtrar o ruído.
Eu tentei com pólos em 0,25, 0,50 e 0,75. Postes pequenos não tiveram muito efeito, e postes maiores adicionaram muita latência, então tive que diminuir os ganhos para mantê-lo estável, resultando em pior desempenho geral.
Adicionei um capacitor de 0,1 µF no potenciômetro (entre o limpador e o terra), e isso parece limpá-lo.
Por enquanto, funciona bem o suficiente. Enquanto isso, estou lendo o artigo publicado por Tim Wescott .
Obrigado a todos por sua ajuda.
This device is suitable for use in switching applications at frequencies up to 5 kHz.
Mas as características elétricas na página 3 sugerem um máximo absoluto de 690kHz se você adicionar todos os atrasos. (linhas de fundo 4) Pessoalmente, eu iria muito mais devagar do que isso, mas acho que 31kHz deveria ser adequado ... se não fosse a nota na página 1.