conteggio variabile ingresso 1-5V

Buongiorno a tutti,

ancora una volta scusatemi se vi chiedo aiuto, ma spero che visto che non sono molto esperto di queste cose potreste darmi una mano (potreste anche dire: perché allora non lasci stare?? ]:))

dovrei registrare il numero di impulsi provenienti da un misuratore di gas. Provo a spiegarmi meglio: lo strumento (SMC-PFM7) manda un impulso per ogni 0,1 NL di gas che passa dallo strumento. Volevo prendere il segnale con un ingresso digitale ma lo strumento manda un impulso (credo a 24VDC), ma quando è in quiescenza è a 1V. (allego una parte del foglio di istruzioni).

Uso questo sketch:

///////variabili
unsigned long contatore = 0; 
int stato; // dove registrare la pulsazione
int oldStato; 
const int sensoreCO2 = 4;  // sensore contatore

////  e nel loop:


  stato = digitalRead(sensoreCO2);
 
  if (stato != oldStato){
    contatore ++;
    stato = oldStato;

  }

lo sketch funzione bene se collegato a un pulsante, ma la variabile non si incrementa con lo strumento attaccato. Ho fatto un partitore di tensione con una R1 da 4,7K e una R2 da 1K.

Qualcuno ha qualche consiglio?

Grazie infinite, e scusate la mia poca dimestichezza con queste cose.

Giacomo

Schermata 2014-05-14 alle 11.37.06.jpg

prima di tutto, sigla completa del flussostato, per capire che tipo di uscite ha
e poi... come lo hai collegato ?

Grazie mille per l'interessamento.

Il flussostato è il PFM710-C6-E. Forse nel post precedente ho fatto un po di confusione.

ho collegato il + e - a un alimentatore da 24VDC, il cavo bianco (che manda il segnale analogico (è quello 1-5V)) è su un pin analogico che mi misura il flusso istantaneo. Su questo non ho problemi.

il cavo nero, che dovrebbe mandare l'impulso della portata accumulata l'ho collegato al pin 4 digitale, mettendo un partitore di tensione con R1 4,7K e R2 1K ( la tensione in uscita dovrebbe essere quella pilotata dall'alimentazione tramite in transistor? con il tester non riesco misurare la tensione perché è troppo veloce (50 ms) e mi segna 8 - 10V per impulso). Il - dell'alimentatore l'ho messo in comune con il GND di Arduino.

Giacomo.

Strano, sembra collegato giusto

Non e' che nello sketch che usi hai dei ritardi, mi provi a vedere se usando gli interrupt legge correttamente

const byte sensoreCO2 = 2;
volatile unsigned long contatore = 0; 

// Interrupt Service Routine (ISR)
void pinChange ()
{
  contatore ++ ;
}  

void setup ()
{
  Serial.begin (9600);
  attachInterrupt (0, pinChange, RISING);  // attach interrupt Timer0 su pin 2
}  

void loop ()
{
  Serial.println ( contatore) ;
  delay(200);
}

ps, il sensore va' collegato sul pin D2

Brunello:
Non e' che nello sketch che usi hai dei ritardi, mi provi a vedere se usando gli interrupt legge correttamente ...

DEVE usare interrupt ... altrimenti NON ha alcuna garanzia che quando ci sarà il breve impulso il programma stia passando proprio per l'istruzione della lettura della porta ... e non facendo qualche altra cosa che non vediamo/sappiamo ... :wink:

Guglielmo

DEVE usare interrupt

infatti e' quello che suggerivo
Pero' c'e' da dire che l'impulso dura 50ms e dato che non credo vengano sparati a raffica

manda un impulso per ogni 0,1 NL di gas che passa dallo strumento

qualcosa doveva leggere comunque

Brunello:
qualcosa doveva leggere comunque

... purtroppo non vediamo cosa fa all'interno del loop() e non sappiamo se c'è un qualche cosa che magari lo impegna per T > 50 msec., nel qual caso ... quando vai a leggere il pin magari è già tornato a riposo ... :roll_eyes:

Guglielmo

Ho provato il codice postato e funziona :roll_eyes:,

credo che il problema era nel codice. Usando attachinterrupt mi è anche più semplice visto che con il codice che avevo fatto io ogni cambiamento di stato mi incrementava la variabile di 1, e quindi dovevo dividere la variabile contatore per 2. Ho fatto delle prove: al massimo della portata manda un impulso ogni 500 ms circa, quindi credo che non ci sia il probema che mi salti qualche impulso?

Vi ringrazio ancora infinitamente, senza di voi sarei spacciato.

Giacomo

ecco il codice completo di prima

#include <SD.h> 

//SPI SD Card Pins
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
int CS_pin = 10;

long id = 1;    
char tempOk1[10];
float temp1;
char tempOk2[10];
float temp2;
int CO2;

unsigned long contatore = 0; 
int state; 
int oldState;
long previousMillis = 0;
long interval = 1000;
int sensoreCO2 = 4;

void setup()
{

  Serial.begin(9600);
  Serial.println("Initializing Card");

  pinMode(CS_pin, OUTPUT);
  pinMode(2, OUTPUT);                           //alimentazione sonda temp1
  pinMode(3, OUTPUT);   // alimentazione sonda temp2
  pinMode(sensoreCO2, INPUT);


  if (!SD.begin(CS_pin))
  {
    Serial.println("Card Failure");
    return;
  }
  Serial.println("Card Ready");

  File logFile = SD.open("LOG.txt", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , ,");
    String header = "tempo, Temp1, Temp2, CO2, Luce1, Luce2";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }

}


/////    ///////         LOOP ///////



void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval){
    previousMillis = currentMillis;

    temp1 = read_temp1();
    temp2 = read_temp2();
    CO2 = analogRead(A2);


    //Create Data string for storing to SD card
    //We will use CSV Format  
    String dataString = String(id) + ", " + dtostrf(temp1, 2, 2, tempOk1) + ", " + dtostrf(temp2, 2, 2, tempOk2) + ", " + String(CO2) + ", " + String(contatore); 

    //Open a file to write to
    //Only one file can be open at a time
    File logFile = SD.open("LOG.txt", FILE_WRITE);
    if (logFile)
    {
      logFile.println(dataString);
      logFile.close();
      Serial.println(dataString);
    }
    else
    {
      Serial.println("Couldn't open log file");
    }

    //Increment ID number
    id++;

    Serial.flush();
  }


  state = digitalRead(sensoreCO2);

  if(state != oldState){
    contatore++;
    oldState = state;
  }


}

GiacomoSam:
Ho fatto delle prove: al massimo della portata manda un impulso ogni 500 ms circa, quindi credo che non ci sia il probema che mi salti qualche impulso?

Usando gli interrupt ? ... tranquillo anche se ne mandava 1 ogni millisecondo di durata 100 ns non lo perdevi :grin: :grin: :grin:

L'interrupt INTERROMPE qualsiasi cosa la MCU stia facendo e fa eseguire l'apposita routine ... dopo di che riprende da dove aveva lasciato :wink:

Guglielmo

Funziona tutto alla perfezione e il numero di impulsi registrati da Arduino combaciano con quelli visualizzati sul monitor dell'apparecchio.

posto il codice completo e aggiornato con attachinterrupt, magari può servire a qualcuno.

#include <SD.h> 

//SPI SD Card Pins
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
int CS_pin = 10;

long id = 1;    
char tempOk1[10];
float temp1;
char tempOk2[10];
float temp2;
int CO2;

volatile unsigned long contatore = 0; 
int state; 
int oldState;
long previousMillis = 0;
long interval = 1000;
const byte sensoreCO2 = 2;

void pinChange(){
 contatore ++; 
}


void setup()
{

  Serial.begin(9600);
  Serial.println("Initializing Card");

  pinMode(CS_pin, OUTPUT);
  pinMode(4, OUTPUT);                           //alimentazione sonda temp1
  pinMode(3, OUTPUT);   // alimentazione sonda temp2
  pinMode(sensoreCO2, INPUT);
  attachInterrupt(0, pinChange, RISING);


  if (!SD.begin(CS_pin))
  {
    Serial.println("Card Failure");
    return;
  }
  Serial.println("Card Ready");

  File logFile = SD.open("LOG.txt", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , ,");
    String header = "tempo, Temp1, Temp2, CO2, Luce1, Luce2";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }

}


/////    ///////         LOOP ///////



void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval){
    previousMillis = currentMillis;

    temp1 = read_temp1();
    temp2 = read_temp2();
    CO2 = analogRead(A2);


    //Create Data string for storing to SD card
    //We will use CSV Format  
    String dataString = String(id) + ", " + dtostrf(temp1, 2, 2, tempOk1) + ", " + dtostrf(temp2, 2, 2, tempOk2) + ", " + String(CO2) + ", " + String(contatore); 

    //Open a file to write to
    //Only one file can be open at a time
    File logFile = SD.open("LOG.txt", FILE_WRITE);
    if (logFile)
    {
      logFile.println(dataString);
      logFile.close();
      Serial.println(dataString);
    }
    else
    {
      Serial.println("Couldn't open log file");
    }

    //Increment ID number
    id++;

    Serial.flush();
  }

}

float read_temp1(void){
  float v_out1;
  float temp1;


  digitalWrite(A0, LOW);

  digitalWrite(4, HIGH);
  delay(2);
  v_out1 = analogRead(A0);
  digitalWrite(4, LOW);

  v_out1*=.0048;
  v_out1*=1000;
  temp1=0.0512*v_out1-20.5128;
  return temp1;

}

float read_temp2(void){
  float v_out2;
  float temp2;


  digitalWrite(A1, LOW);

  digitalWrite(3, HIGH);
  delay(2);
  v_out2 = analogRead(A1);
  digitalWrite(3, LOW);


  v_out2*=.0048;
  v_out2*=1000;
  temp2=0.0512*v_out2-20.5128;
  return temp2;

}

Grazie mille ancora,

Giacomo.

ma a leggere lo stato di un pin ci mette pochi ns? Quindi anche se l'impulso combacia con la scrittura sulla sd card non c'è problema?

Giacomo.