Automação corte Laser

Olá pessoal, bom dia.

Estou trabalhando em um projeto de uma automação do ar comprimido em uma máquina de corte laser.
As máquinas de corte laser usam o ar comprimido empurrar a fumaça residual do processo para o exaustor.

A idéia é básica seria utilizar sensores óticos e um disco de encoder dos eixos x e y para monitorar a rotação e manter uma válvula solenoide ligada através de um relê para fechar ou abrir a linha de ar comprimido caso haja movimento ou a ausência dele.

Componentes utilizados:

1 Relê

1 Par de sensores óticos

E 1 Arduíno nano.

Tentativas:

Primeira tentativa: Defini as variáveis e defini tempos de atrasos para que o pino de saída se mantivesse e estado alto quando houvesse movimento. Sem sucesso.

int rele = 8; //Declara o pino 8 como rele
int encoder1 = 2; //Declara o pino2 como encoder 1
int encoder2 = 3; //Declara o pino3 como encoder 2

void setup()
{
Serial.begin(9600);
pinMode(rele, OUTPUT); //a variável rele é declarada como saída
pinMode(encoder1, INPUT); //a variável encoder1 é declarada como entrada
pinMode(encoder2, INPUT); //a variável encoder2 é declarada como entrada
}

void loop()
{
while (digitalRead(encoder1) == 1)
digitalWrite(rele, HIGH); //se encoder 1 é maior que 0, rele ligado
delay(1000); //espera 10s
while (digitalRead(encoder2) == 1)
digitalWrite(rele, HIGH); //se encoder 2 é maior que 0, rele ligado
delay(1000); //espera 10s
while (digitalRead(encoder1) == 0)
digitalWrite(rele, LOW); //se encoder 1 é maior que 0, rele ligado
delay(1000); //espera 10s
while (digitalRead(encoder2) == 0)
digitalWrite(rele, LOW); //se encoder 2 é maior que 0, rele ligado
delay(1000); //espera 10s

}

Segunda tentativa:

Tentando monitorar o RPM, utilizei um código que encontrei na net e tentei manter o estado do relê alto. Sem sucesso também.

int ledPin = 13; // IR LED connected to digital pin 13
int statusPin = 12; // LED connected to digital pin 12

volatile byte rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;

void rpm_fun()
{
//Each rotation, this interrupt function is run twice, so take that into consideration for
//calculating RPM
//Update count
rpmcount++;

//Toggle status LED
if (status == LOW) {
status = HIGH;
} else {
status = LOW;
}
digitalWrite(statusPin, status);
}

void setup()
{
Serial.begin(9600);
//Interrupt 0 is digital pin 2, so that is where the IR detector is connected
//Triggers on FALLING (change from HIGH to LOW)
attachInterrupt(0, rpm_fun, FALLING);

//Turn on IR LED
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);

//Use statusPin to flash along with interrupts
pinMode(statusPin, OUTPUT);

rpmcount = 0;
rpm = 0;
timeold = 0;
status = LOW;
}

void loop()
{
//Update RPM every second
delay(1000);
//Don't process interrupts during calculations
detachInterrupt(0);
//Note that this would be 60*1000/(millis() - timeold)rpmcount if the interrupt
//happened once per revolution instead of twice. Other multiples could be used
//for multi-bladed propellers or fans
rpm = 30
1000/(millis() - timeold)*rpmcount;
timeold = millis();
rpmcount = 0;

//Write it out to serial port
Serial.println(rpm,DEC);

//Restart the interrupt processing
attachInterrupt(0, rpm_fun, FALLING);

}

Caso alguém tenha alguma idéia e puder contribuir, ficaria muito grato.

Obrigado

No primeiro codigo nao funciona porque nao estas a ver o movimento, mas sim onde e que o disco esta. Ou seja, o disco pode estar parado e a saida sempre a funcionar...

O segundo codigo e confuso demais.... e pior, tem delays.

Sabes qual e a velocidade da maquina? Velocidade minima e velocidade maxima? Se sabes isso, podes calcular qual e o pulso de encoder mais longo que vais ter. Assim, e de forma um pouco "sapateira", podes:

unsigned char before = 0
unsigned char now = 0;
unsigned char status = 0;
unsigned long time = 0; 

void loop() {

now = digitalRead(pino); 


//codigo para ligar o rele. 
if (now != before && status == 0) { //detecta pulso... 
   digitalWrite(rele, HIGH); 
   status = 1; 
   time = millis();
}

// codigo para desligar o rele
if (status == 1 && (time-millis() > XXXX)) {
   //passou muito tempo, desliga o rele. 
   digitalWrite(rele, LOW);
}

//codigo para manter o rele ligado. 
if(status ==1 && now != before) {
   time = millis():
}

before = now;
}//end loop

O codigo detecta uma transicao num dos sensores e liga o rele e lanca um timer.

Se o rele estiver ligado e o tempo entre a ultima activacao e tempo actual e maior do que a velocidade minima a que a maquina vai funcionar, entao, desliga o rele.

Se o rele esta ligado e houve mudanca de estado no sensor, entao nao queremos que o rele desligue. Para tal, actualizamos a variavel time, para garantir que o segundo if nao se realiza.

A variavel XXXX tem de ser ajustada por ti dependendo da velocidade. Nota que aquele valor e tempo em milissegundos.

Se quiseres ver as velocidades podes fazer algo como aqui em baixo num programa separado:

now = digitalRead(pino);

if (now != before) {
   Serial.println(time-millis());
   time = millis();
}

before = now;

O serial port vai indicar-te os tempos entre activacoes (flanco positivo e negativo) do encoder.

Esta e uma maneira de resolver o problema... se o codigo das velocidades funciona, so tens de colocar um if para ligar o rele.

  while (digitalRead(encoder1) == 0)
    digitalWrite(rele, LOW); //se encoder 1 é igual que 0, rele desligado
    delay(1000);              //espera 10s
 while (digitalRead(encoder2) == 0)
    digitalWrite(rele, LOW); //se encoder 2 é igual que 0, rele desligado
    delay(1000); //espera 10s

Acho que queria dizer caso que caso igual a 0, o rele desliga