Hello everyone! I am new here and also to micro controller programming. I find working with MCs it fascinating and also frustrating, especially when things don't go as planned. I ran into an issue that hopefully, someone else has too, and there is a solution to it.
The project involves simulating pulses from a natural gas meter, industrial style, in order to measure instantaneous gas flow in cubic feet per hour. The device, a Volume Converter, I am feeding the pulses to, is highly accurate and has gone through rigorous testing incl. also has 3rd body certification, no issue there.
The required pulses are of longer durations then a PWM can handle, at least that is my believe. For example: for a flow of 160 cubic feet an hour, a continuous pulse with a width of >=40ms<=150ms and a delay of 36000ms (rising to rising) is required; that represents 1% of the gas meters capacity. For a flow of 100% capacity, a continuous pulse with a width of >=40ms<=150ms and a delay of 360ms (rising to rising) is required. That gives a range from 36000ms (1%) to 360ms (100%). I have used the below code to generate the pulse with an Arduino Nano Every, 3600ms delay and 75ms width; forgive me if it's not the best solution; I am open to suggestions.
//Pulse output
#define DI1_OUT 3
unsigned long interval1 = 0;
unsigned long currentMillis = 0;
unsigned long currentMillis1 = 0;
unsigned long previousMillis1 = 0;
unsigned long currentMillisP = 0;
unsigned long currentMillisP1 = 0;
unsigned long previousMillisP1 = 0;
signed long timeDif1 = 0;
const int pulseWidth = 75; //>=40ms<=150ms
int pulseWidth1 = -1;
void setup(){
Serial.begin(115200);
pinMode(DI1_OUT, OUTPUT);
}
//Main program
void loop()
{
interval1 = 3600;
//Qu 1:
currentMillis = millis();
currentMillis1 = currentMillis;
timeDif1 = currentMillis1 - previousMillis1 - interval1;
if (timeDif1 >= 0) {
digitalWrite(DI1_OUT, HIGH);
Serial.print(currentMillis1 - previousMillis1);
previousMillis1 = currentMillis1; //save the last time for LED HIGH
previousMillisP1 = currentMillis1; //start pulseWidth 1
pulseWidth1 = pulseWidth;
}
currentMillisP = millis();
currentMillisP1 = currentMillisP;
// Pulse Width 1:
if (currentMillisP1 - previousMillisP1 >= pulseWidth1) {
digitalWrite(DI1_OUT, LOW);
Serial.print("\t");
Serial.println(currentMillisP1 - previousMillisP1);
previousMillisP1 = currentMillis1;
pulseWidth1 = -1;
}
}
This is working fine and the values printed on the serial port are accurate. The problem is the pin output; it's not accurate and fluctuates to the extent that the device doesn't show a stable flow. To further investigate, I used a second board, an Arduino Uno R4 Minima, to measure the outgoing pulses; see code below:
#define Pulse1In 2
int pin1_Start = -1;
unsigned long pulse1millis = 0;
unsigned long currentMillisP1 = 0;
unsigned long pulse1Start = 0;
unsigned long pulseWidth1 = 0;
void setup() {
pulse1Start = micros();
Serial.begin(115200);
pinMode(Pulse1In, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(Pulse1In),CheckPulse1, CHANGE);
}
void CheckPulse1(){
pin1_Start = 1;
}
void loop() {
if (pin1_Start == 1){
currentMillisP1 = micros();
pulseWidth1 = currentMillisP1 - pulse1Start;
Serial.println(pulseWidth1/1000);
pulse1Start = currentMillisP1;
pin1_Start = 0;
}
}
I used the status CHANGE as it returns both values, the pulse delay and the pulse width, and I am also measuring in microseconds. Here is what I am reading the above settings of 3600ms (10%) and 75ms on the sending device:
3525029
74810
3524654
75862
3525596
74832
3525891
74827
The reading on the sending device is stable at 3600ms and 75ms. At a setting of 360ms/75ms, the readings are closer but the error in % is bigger.
285764
74858
284776
75895
284776
74869
284780
75891
284785
74867
The Volume Converter shows a fluctuating flow of 15984 -15995 cubic feet an hour; not quite the result I expected. As you can see, the sending device, an Arduino Nano Every, calculates the pulse delay and width correctly, but it can't seem to output it with the same precision? Maybe using an Interrupt Timer may help? Any help, comments are appreciated.