Boa noite pessoal, estou com uma séria dificuldade pra desenvolver meu TCC que é um projeto de uma injeção eletrônica com arduino, basicamente estou querendo fazer a leitura do RPM, Ãngulo de posição da borboleta, e gerar um pulso PWM onde o duty cicle vai variar conforme o potenciometro da borboleta. Tenho o código que estarei inserindo abaixo que por enquanto não funciona, gostaria de ver se alguém tem alguma luz sobre o que está errado nesse código. 

/* Firmware - controleInjecaoEletronica
Renato Silva de Carvalho


Este firmware tem a finalidade de fazer o controle
da injecao de combustivel atraves do sensoriamento
da rotacao e sensor de posicao da borboleta
*/

#include <LiquidCrystal.h>


LiquidCrystal lcd(13,12,11,10,9,8);


// Variaveis

int injetor = 6;
int borboleta = A0;
int janela = 0;
float Borboleta;
float tps; //Variavel para receber a variação da posição da borboleta
const long int periodo = 500000; // definindo o periodo
unsigned long voltaVolante = 0; // Rotacao do motor
unsigned long time = 0; // Tempo total
unsigned long tempRotMot = 0 ;
unsigned long ti = 0 ;
unsigned long tioff = 0 ;


void rotacaoMotorInterrupt()
{
long aux = 0;
time = millis(); //mili S
aux = time - voltaVolante; // diferença entre o tempos
voltaVolante = time;
tempRotMot = aux;
}

void setup ()

{

lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("INJ ELETRONICA");

pinMode (injetor, OUTPUT);

delay (2000);

attachInterrupt(0, rotacaoMotorInterrupt, RISING); // Interrupcao na saida da porta 2 (0 = a porta 2)


}

void loop ()

{

Borboleta = analogRead(borboleta);

// map it to the range of the analog out:
tps = map(Borboleta, 0, 1023, 0, 90);

janela = ((1/(tempRotMot/60))* 1000);

// vai iniciar um duty cicle minimo de 5% da janela
// somando a porcentagem de 0 a 90% que sera referente ao
// angulo de aceleracao

ti = ( (janela * 0.05) + ((janela * tps) / 100) );
tioff = (janela - ti);

// acionamento do Injetor

digitalWrite (injetor, HIGH);
delay (ti);
digitalWrite (injetor, LOW);
delay (tioff);

}

void telaLcd()
{

lcd.setCursor(0, 0);
lcd.print("PER.:");
lcd.print(janela);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("TPS:");
lcd.print(tps);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print("RPM:");
lcd.print(tempRotMot);
lcd.print(" ");

}

Exibições: 10096

Responder esta

Respostas a este tópico

Você não pode usar o PWM do microcontrolador?

https://www.arduino.cc/en/Reference/AnalogWrite

   Bom dia, o grande problema da geração desse pwm é que tem tem de ser sincronizado com o sinal do distribuidor que é um sinal quadrado de 5 volts. O que eu preciso fazer é gerar um pwm em toda borda de subida desse sinal e controlar o duty cicle pra fazer o ajuste.

    Tem alguma idéia de como fazer isso?

Oi RSC, bom dia.

Me corrija se eu estiver errado:

Você quer um pulso em um port digital de um arduino, em que o tempo dele em HIGH, seja

variado em função da posição de um potenciômetro acoplado na borboleta, e sincronizado

com algum sensor que mede a rotação do motor.   Correto?

Perguntas:  

    1. Esta borboleta está onde e como é variada a posição dela?

    2. Qtos cilindros tem o motor e como saberá quando acontece o tempo de cada cilindro?

    3. O que não funciona no seu code atual?  Ou code deveria funcionar?

         Tem muito pouco comentários no seu code. 

Rui

   Rui, realmente comentei pouco o código, na verdade será um sistema para controle de somente 1 bico injetor, motor de 4 cilindros, e o tempo da injeção não tem muita relevancia, já que o combustível seguirá pelo tbi pulverizado e o vácuo do motor se encarregará de puxar ar e o combustível injetado para dentro do motor.

  

     A borboleta está no coletor de admissão de Ar. O sensor é acoplado na base da borboleta e varia de 0 a 5 volts.

           O que não funciona é a saída, já consegui ler rotação, porém não consigo processar.

     O que preciso é somente de um pwm sincronizado com o sinal quadrado que o processador estará recebendo do distribuidor, que tem um sensor hall acoplado que estará enviando um sinal quadrado de 0 a 5 volts. 

  

    Se conseguirmos disparar um PWM sincronizado e controlar o duty cicle já é o bastante para que eu trabalhe no ajuste do funcionamento no motor.

Estou ha algumas semanas tentando desenvolver um medidor de RPM para motores de passo. 

E estou chegando à conclusão que o Arduino (Uno, Nano) não tem precisão que eu espero. 

Testei vários sketches de medição de largura de pulsos e RPM , e não gostei...

As medições ficam variando... (muito ruim isso) - devido à baixa resolução dos timers internos do ATmega328.

Talvez tenha que usar um Arduino DUE ( mais rápido e mais sofisticado). 

O RPM, para sinal quadrador encontrei um tutorial no youtube e parece que funciona, estou tentando simular ele aqui no isis pra confirmar, é esse o link, vou te enviar o código tbm pra vc dar uma olhada, a programação está toda em baixo nível, o professor que postou esse vídeo programou diretamente nos registradores.

//#include "C:/Engineering/Libraries/Code/AVR/defines.h"
#include <avr/io.h>
//#include <avr/interrupts.h>
#include <stdlib.h>
#include <util/delay.h>
//#include "C:/Engineering/Libraries/Code/AVR/lcd/hd44780.h"


volatile unsigned int tachTimer;
volatile unsigned long tachometer;

#define TIMER_OFF 0b00000000
#define TIMER_ON 0b00000101 // divide system clock by 1024 - 51.2usec per tick
// this factor converts the time measured for each revolution of the shaft to
// RPM.
// the timer ticks once every 51,2usec (the / 512 factor), 60 revolution per
// minute. The 10000000 converts us to seconds.

#define TIMER_TO_TACH (60UL * 10000000UL / 512UL)

int main(void){
char tempStr[10];
//hd44780_init (&PORTD, PORTD7, &PORTB, PORTB1, &PORTB, PORTB0, 2, 20);

//setup the external interrupt 0 (INT0) pin
DDRD &=~_BV(PORTD2);
EICRA |=_BV(ISC01); // INT0 generates interrupt on falling edge
// setup timer 1 to measure the time between interrupts
TCCR1A = 0b00000000; // reset state, just a counter that increments
TCCR1B = TIMER_OFF;
TCNT1 = 0

'while' (1);
{
while ((EIFR &_BV (INTF0)) == 0);
TCCR1B = TIMER_ON; // turn on the timer
GTCCR |= _BV(PSRSYNC); // reset the tmer pre-scaler
EIFR = _BV (INTF0); // clear the interrupt flag

while ((EIFR&_BV (INTF0)) == 0;
TCCR1B= TIMER_OFF; // turn off the timer
tachTimer = TCNT1;
TCNT1 = 0;

tachometer = TIMER_TO_TACH / (unsignedlong)tachTimer;
Ltoa (tachometer, tempStr, 10);
//hd44780_clearLine(0);
//hd44780_putctr (tempStr);
EIFR = _BV (INTF0); // clear the interrupt flag

}
}

Colega ja estudei bastante os timers do Arduino. 

Veja no seu exemplo :

divide system clock by 1024 - 51.2usec per tick 

Nos timers do Arduino existe uma imprecisão de até 4 us !! Quer dizer, quase 10% da base de tempo do seu sketch. E o pior , essa imprecisão varia com o tempo (dentro da rotina). 

Não faça simulações - faça testes reais. Vai por mim. 

Existe uma solução gambiarra, para filtrar essas variações de tempo/medições, usando calculo de médias. Mas não aprecio isso. 

Deixa eu te perguntar, vc acha que dá pra fazer essa função que preciso pra controlar a injeção eletrônica com o Arduino? O que está se fazendo um pouco complexo é gerar um PWM através da onda quadrada que vem do distribuidor, daí conseguindo variar o duty cicle conforme o potenciometro já conseguiria um ajuste do quanto deve injetar de combustível.

Oi JGAM, bom noite.
Estou estranhando este comportamento dos arduinos qto a imprecisão das medidas.

Não é possivel fazer testes aqui onde estou, mas fazendo uma analise simples.

Estabelecendo entre velocidade de 42 RPM até 4200 RPM, temos;

42 RPM = 0,7 RPS +- 0,7 Hz
4.200 RPM = 70 RPS +- 70 Hz

Encoder de 60 pulso acoplado ao eixo

0,7 RPS = 42 Hz
70 RPS = 4.200 Hz

Se voce usar a bibiloteca TimerOne para medir o tempo, e usar o interrupt externo para

contar os pulsos, acredito que terá uma boa precisão.

Eu uso esta biblioteca para controle de dimmer e tem um bom resultado.
Uso para controle de 10ms.

Para testar aqui,  fiz assim:


Gravei um code em um arduino DUE gerando 2000 HZ de PWM,
Joguei este sinal no port 2 de um arduino mini com o code em anexo.


Simulando um encoder de 60 pulsos.

Medi a rotação a cada 100 ms.


33,33 RPS = 2000 RPM

Rui

Serial com RPM

Anexos

   Boa noite, estava testando o seu tacometro e vi que funciona com uma boa precisão, você sabe se dá pra gerar um PWM na mesma frequência do sinal que está entrando na porta 2, se eu conseguir gerar uma saída  PWM que possa variar o duty cicle conforme a variação de um potenciometro que será no caso o sensor de posição da borboleta, meu problema estará solucionado.

        

Oi RSC, boa noite.

Você quer gerar este PWM em outro arduino? 

Sim é possível.  E é possível também que ele tenha um duty cycle ajustável

de acordo com o valor lido de um potenciômetro.

Use este mesmo recurso do TimerOne, e só dispare o pulso qdo receber um sinal

ou no port 2 ou 3 (interrupt externo).

Faça um mapa da medida do potenciômetro, e faça a duração do pulso

proporcional à esta medida.

Rui

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço