Sending ASCII Commands to a Teensy 3.5 Via RS232 to TTL Converter

ATORTeensyMan

Active member
Hello guys! So, my issue is that I'm attempting to send ascii commands and in return I want to be able to read the outputted response of a sensor. For example, I want to send b'DAFxxxx0005\r\n' then in return the sensor should send 5 readings on one line of Flow in LPM. I have Python code I wrote that does exactly what I want between a pc and the sensor just to show more in depth what I want to achieve between the sensor and teensy. (RX = 0, TX=1)
Code:
import serial
import time

index = 0
total = 0
i = 0
avg = 0

# Serial Connection
time.sleep(.5)
ser = serial.Serial(
        port="COM13", baudrate = 115200,
        parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS, timeout=1)

# Write ASCII Commands To TSI 5300 Flow Sensor
ser.write(b'?\r\n') # Ask Sensor if it is getting a signal (Returns "OK")
ser.write(b'SUS\r\n') # Set Flow type to SLPM (Returns "OK")
ser.write(b'SG0\r\n') # Set Flow Gas to Air (Returns "OK")
ser.write(b'SSR0005\r\n') # Set Sample Rate to 5ms (Returns "OK")
ser.write(b'LPZ\r\n') # Zero Low Pressure Sensor

# Read serial output to remove all 'OK's from buffer
while (i <= 4):
    ser.readline() # Read one line of serial and discard it
    i += 1

# Loop infinite flow readings until Flow is <= to 85 LPM
while (avg <= 85):
    index = 0
    total = 0

    ser.write(b'DAFxxxx0005\r\n') # Read 5 sensor Flow Reading
    ser.readline() # Read one line of serial data and discard it
    byte = ser.readline() # Read one line of serial data and store it
    string = byte.decode('utf-8') # Convert from BYTE to STRING
    array = string.split(',') # Convert from STRING to STRING ARRAY
    
    # Convert each element of the ARRAY to FLOAT then add them together
    for data in array:
        index += 1 
        data = float(data)
        total += data

    avg = total / index # Find the average Flow in LPM
    print(avg)
    time.sleep(1)

ser.close()
 
Code:
import serial
import time

index = 0
total = 0
i = 0
avg = 0

# Serial Connection

time.sleep(.5)
ser = serial.Serial(
    port = "COM13", baudrate = 115200,
    parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS, timeout = 1)

    # Write ASCII Commands To TSI 5300 Flow Sensor

    ser.write(b'?\r\n')                         # Ask Sensor if it is getting a signal(Returns "OK")
    ser.write(b'SUS\r\n')                       # Set Flow type to SLPM(Returns "OK")
    ser.write(b'SG0\r\n')                       # Set Flow Gas to Air(Returns "OK")
    ser.write(b'SSR0005\r\n')                   # Set Sample Rate to 5ms(Returns "OK")
    ser.write(b'LPZ\r\n')                       # Zero Low Pressure Sensor

    # Read serial output to remove all 'OK's from buffer

    while (i <= 4) :
        ser.readline()                          # Read one line of serialand discard it
        i += 1

        # Loop infinite flow readings until Flow is <= to 85 LPM

        while (avg <= 85) :
            index = 0
            total = 0

            ser.write(b'DAFxxxx0005\r\n')       # Read 5 sensor Flow Reading
            ser.readline()                      # Read one line of serial data and discard it
            byte = ser.readline()               # Read one line of serial data and store it
            string = byte.decode('utf-8')       # Convert from BYTE to STRING
            array = string.split(',')           # Convert from STRING to STRING ARRAY

            # Convert each element of the ARRAY to FLOAT then add them together

            for data in array:
index += 1
data = float(data)
total += data

avg = total / index                             # Find the average Flow in LPM
print(avg)
time.sleep(1)

ser.close()
Can I suggest that when you present code for analysis that you separate the comments from the actual code by "White Space".
It's good that you have comments, but doing what I suggest makes both the code and the comments stand out.

What you want to do should be very achievable.
If you are having a problem, you have not said what it is.
 
Hello guys! So, my issue is that I'm attempting to send ascii commands and in return I want to be able to read the outputted response of a sensor. For example, I want to send b'DAFxxxx0005\r\n' then in return the sensor should send 5 readings on one line of Flow in LPM. I have Python code I wrote that does exactly what I want between a pc and the sensor just to show more in depth what I want to achieve between the sensor and teensy. (RX = 0, TX=1)

@ATORTeensyMan:

My understanding from your initial post is that you want to write a sketch for your Teensy which will accomplish the same functionality as the Python code that you included. I would encourage you by saying that what you want to do can certainly be accomplished using the Teensy. I see from the title of your post that you seem to be using the T3.5. I have not used that specific Teensy, but I have created several successful project that make use of the serial ports on the T4.0 & T4.1, so don't be afraid to press forward. I don't know what level of Teensy experience that you're currently at, but I would recommend as a start that you take a look at the "ReadAcsiiString" example to see 1) the general layout of a Teensy sketch using serial, 2) how to setup & use the serial port, & 3) how to read values from the Teensy serial port. The "SerialCallResponse" example may also have some useful tidbits.

Please feel free to ask any other questions, as you have fellow forum members on here who are happy to help & answer questions. For future posts, if you have specific Teensy code giving you problems, remember that it's much easier for us to provide help if you also post the specific code that you are working on. Posting your Python code as you did to show what you are after was a very good start !!

Good luck & have fun !!

Mark J Culross
KD5RXT
 
I think you will find the code below will achieve your purpose.
Code:
/*
    Created:	01/03/2022 14:27:15
*/

uint32_t    idx, i;
float       total   = 0.0;
float       avg     = 0.0;

uint8_t     responseTimeout = 1000;     // 1000 ms = 1 Second

bool        flowMeterSetup  = false;
float       result;

/******************************************************************
*          Send command in s to flowmeter over Serial1            *
*    If len=0 then just decode data still in the serial buffer    *
*-----------------------------------------------------------------*
*       Wait until timeout or data is terminated with             *
*       the chars "OK" in that order.                             *
*-----------------------------------------------------------------*
*    The result is placed in the global float variable "result".  *
*    Characters other than "0".."9",".","O"and "K" are ignored.   *
*******************************************************************/

bool SendCommandToFlowMeterGetResult(const char* s, unsigned int len) {
    elapsedMicros   timeout = 0;
    uint8_t         n       = 0;
    uint8_t         dpPos   = 0;
    uint8_t         count   = 0;
    char            c;
    bool            gotOK   = false;

    while (Serial1.peek() == '/n' || Serial1 == '/r') {
        c = Serial1.read();  //throw away /n and/or /r
    }

    if (len > 0) {
        Serial1.write(s, len);
    }

    result = 0.0;
    count  = 0;

    while (!gotOK) {

        n = 0;
        while ((n < 4 ) && (responseTimeout < timeout) && !gotOK) {

            if (Serial1.available()) {

                c = Serial1.read();
                if (n == 0) {
                    if (c == 'O') {
                        n++;
                    }
                    else {
                        if ((c >= '0') && (c <= '9') || (c=='.')) {
                            if (c == '.') {
                                dpPos = count;
                            } else {
                               result = result * 10.0 + (float) (c-'0');
                               count++;
                            }
                        }
                    }
                } else if (n == 1 && c == 'K') {
                    gotOK = true;
                }
            }
        }
    }
    if (gotOK) {
        if (count > 0) {
            count -= dpPos;
            while (count > 0) {
                result /= 10.0;
                count--;
            }
        }
    }
    return gotOK;
}

void setup()
{
    Serial.begin(9600);                             // Start USB Serial - Output to PC
    while (!Serial && millis() < 5000) {};          // wait for USB Serial to establish itself

    Serial1.begin(115200);                          // Initialise Uart Port @ 115200
                                                    /*  ser = serial.Serial(
                                                        port = "COM13", baudrate = 115200,
                                                        parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE,
                                                        bytesize = serial.EIGHTBITS, timeout = 1)
                                                    */
    Serial1.write('?\r\n');

    if (SendCommandToFlowMeterGetResult('SUS\r\n',5)) {                           // was Serial1.write('SUS\r\n');     # Set Flow type to SLPM(Returns "OK")
        if (SendCommandToFlowMeterGetResult('SG0\r\n',5)) {                       // was Serial1.write('SG0\r\n');     # Set Flow Gas to Air(Returns "OK")
            if (SendCommandToFlowMeterGetResult('SSR0005\r\n',9)) {               // was Serial1.write('SSR0005\r\n'); # Set Sample Rate to 5ms(Returns "OK")
                flowMeterSetup = (SendCommandToFlowMeterGetResult('LPZ\r\n',5));  // was Serial1.write('LPZ\r\n');     # Zero Low Pressure Sensor
            }
        }
    }
    delay(500);                                                                   // a delay time after setup may be required.
}

void loop()
{
    uint8_t const numReadings = 5;

    i = 0;
    idx = 0;
    if (flowMeterSetup) {
        while (avg < 85.0) {
            idx = 0;
            total = 0.0;
            for (idx = 0; idx++; idx < numReadings) {
                if (idx == 1) {
                    if (SendCommandToFlowMeterGetResult('DAFxxxx0005\r\n', 13)) {
                        Serial.println(F("DAFxxxx0005\r\n: Errors Getting Data from flowmeter"));
                    }
                }
                else
                {
                    if (SendCommandToFlowMeterGetResult('1', 0)) {
                        Serial.println(F("previous command DAFxxxx0005\r\n: Errors Decoding Precious Data from flowmeter"));
                    }
                    total += result;
                }
            }
            avg = total / (float)numReadings;
        }
    } else
    {
        Serial.println(F("Errors when setting up flowmeter"));
    }
    delay(1500);  //Just sit around for 1.5 seconds
}
 
Hey there sir. So, I tried to use the code above, however I don't think I'm using it correctly? The code doesn't seem to be doing anything at all just an empty serial console. I typed 's' into the console and sent it and nothing happened. Are there things I need to change to fit my use case, because I am at a total loss right now lol. I'm gonna break it down and just try to understand everything your code is trying to achieve.
 
You said NOTHING about actuating the command from the console.
The program that you showed with your post did not do that either.
Anyway there is much contained within the code that I sent you which should allow you to modify the program for your needs.
 
No i dont want to actuate anything from the console, I just thought yours was doing that. What I want is for the thing to turn on and start giving me flow readings until it hits 85.0 LPM. However, when I turn your code on it does nothing. Nothing comes out on the console at all. I'm wondering if my RS232 to ttl converter is connected correctly. My pinout is VCC - 5v, Rx = pin 0, Tx = Pin 1, Gnd - 0v. On the converter itself it has a male end DB9 and it's connected to the Flowmeter by RS232 Female to USB-A right into the meter.
 
In theory if my Meter was connected correctly wouldn't this code (see below) return "OK" in the serial console, but rather I get an empty square. I guess where I am struggling is, how does the teensy associate Serial1 to my teensy pin 0 and 1, because if Serial1 isn't reading those 2 pins exactly then i would never see any data. right?
Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.write('?\r\n');
  s = Serial1.read();
  Serial.println(s);
}

void loop() {
  // put your main code here, to run repeatedly:

}
 
I was using ' where I should be using " which compiled but caused all sorts of problems.
Try the code below. I have separated out the sending of the commands to the flowmeter from getting the response.
It's not as tidy but is easier to debug.
There is one line near the top of the code "bool debug = true;". This causes all sorts of screen output. Set it to false to stop the screen output.
Code:
/*
    Created:	01/03/2022 14:27:15
*/

#define FlowMeter Serial1

uint32_t    idx, i;
float       total = 0.0;
float       avg = 0.0;

uint8_t     responseTimeout = 1000;     // 1000 ms = 1 Second

bool        flowMeterSetup = false;
float       result;
bool debug = true;      // <<--- with this set to true a lot of screen output will be seen
                        // an easy way to debug progress;    

/******************************************************************
*          Send command in s to flowmeter over Serial             *
*    If len=0 then just decode data still in the serial buffer    *
*-----------------------------------------------------------------*
*       Wait until timeout or data is terminated with             *
*       the chars "OK" in that order.                             *
*-----------------------------------------------------------------*
*    The result is placed in the global float variable "result".  *
*    Characters other than "0".."9",".","O"and "K" are ignored.   *
*******************************************************************/

bool GetFlowMeterResult() {
    elapsedMicros   timeout = 0;
    uint8_t         n = 0;
    uint8_t         dpPos = 0;
    uint8_t         count = 0;
    char            c;
    bool            gotOK = false;
    bool            done  = false;

    result = 0.0;
    count = 0;

    while (!gotOK && !done) {

        n = 0;
        while ((n < 4) && ( timeout < responseTimeout) && !gotOK) {
//            if (debug) { Serial.print(n); Serial.print("  "); Serial.print(timeout); Serial.print("/"); Serial.print(responseTimeout); Serial.print("  "); Serial.println(!gotOK); }
            if (FlowMeter.available()) {

                c = FlowMeter.read();
                if (n == 0) {
                    if (c == 'O') {
                        n++;
                    }
                    else {
                        if ((c >= '0') && (c <= '9') || (c == '.')) {
                            if (c == '.') {
                                dpPos = count;
                            }
                            else {
                                result = result * 10.0 + (float)(c - '0');
                                count++;
                            }
                        }
                    }
                }
                else if (n == 1 && c == 'K') {
                    gotOK = true;
                }
            }
        }
        done = (timeout >= responseTimeout);
    }
//    if (debug) { Serial.println(gotOK); }
    if (gotOK) {
        if (count > 0) {
            count -= dpPos;
            while (count > 0) {
                result /= 10.0;
                count--;
            }
        }
    }
    return gotOK;
}

void setup()
{
    Serial.begin(9600);                             // Start USB Serial - Output to PC
    while (!Serial && millis() < 5000) {};          // wait for USB Serial to establish itself
    Serial.println("Setting up UART");
    FlowMeter.begin(115200);                          // Initialise Uart Port @ 115200
                                                    /*  ser = serial.Serial(
                                                        port = "COM13", baudrate = 115200,
                                                        parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE,
                                                        bytesize = serial.EIGHTBITS, timeout = 1)
                                                    */

                                                    //    FlowMeter.write('?\r\n');
    Serial.println("Sending commands to Flowmeter");
    if (debug) { Serial.print("    SUS\r\n"); }
    FlowMeter.print("SUS\r\n");
    if (debug) { Serial.print("    .\r\n"); }
    if (GetFlowMeterResult()) {                           // was FlowMeter.write('SUS\r\n');     # Set Flow type to SLPM(Returns "OK")
        if (debug) { Serial.print("Sending commands to Flowmeter");  Serial.print("    SG0\r\n"); }
        FlowMeter.print("SG0\r\n");
        if (debug) { Serial.print("    SSR0005\r\n"); }
        if (GetFlowMeterResult()) {                       // was FlowMeter.write('SG0\r\n');     # Set Flow Gas to Air(Returns "OK")
            FlowMeter.print("SSR0005\r\n");
            if (GetFlowMeterResult()) {               // was FlowMeter.write('SSR0005\r\n'); # Set Sample Rate to 5ms(Returns "OK")
                if (debug) { Serial.print("    LPZ\r\n"); }
                FlowMeter.print("LPZ\r\n");
                flowMeterSetup = (GetFlowMeterResult());  // was FlowMeter.write('LPZ\r\n');     # Zero Low Pressure Sensor
            }
        }
    }
    delay(500);             // a delay time after setup may be required.
/*
    avg = 85.0124;
    Serial.print("Flowmeter output : ");
    Serial.println(avg);
*/
}

void loop()
{

    uint8_t const numReadings = 5;

    i = 0;
    idx = 0;
    if (flowMeterSetup) {
        while (avg < 85.0) {
            idx = 0;
            total = 0.0;
            for (idx = 0; idx++; idx < numReadings) {
                if (idx == 1) {
                    FlowMeter.print("DAFxxxx0005\r\n");
                    if (GetFlowMeterResult()) {
                        Serial.println(F("DAFxxxx0005\r\n: Errors Getting Data from flowmeter"));
                    }
                }
                else
                {
                    if (GetFlowMeterResult()) {
                        Serial.println(F("previous command DAFxxxx0005\r\n: Errors Decoding Previous Data from flowmeter"));
                    }
                    total += result;
                }
            }
            avg = total / (float)numReadings;
            Serial.print("Flowmeter output : ");
            Serial.println(avg);
        }
    }
    else
    {
        Serial.println(F("Errors when setting up flowmeter"));
    }
    delay(1500);  //Just sit around for 1.5 seconds

}
I'm off to bed now!!
Let me know how it goes.
 
In theory if my Meter was connected correctly wouldn't this code (see below) return "OK" in the serial console, but rather I get an empty square. I guess where I am struggling is, how does the teensy associate Serial1 to my teensy pin 0 and 1, because if Serial1 isn't reading those 2 pins exactly then i would never see any data. right?
Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.write('?\r\n');
  s = Serial1.read();
  Serial.println(s);
}
You don't say which Teensy you are using but the Rx/Tx position is the same for all of them. 
The the diagram attached.

void loop() {
  // put your main code here, to run repeatedly:

}

I think you code snippet had the same problem as me. Change the ' to " and try.
Also your code needs to be as below
Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.print("?\r\n");
  while (Serial1.available()){
    s = Serial1.read();
    Serial.print(s);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}
You don't say which Teensy you are using but they are all the same with respect to RX/Tx position.
See image attached.
Teensy Rx-Tx.png
Now I REALLY am going to Bed!!
 
did read the datasheet
and the returned readings
have the following format

1.10,1.20,1.25,1.23,1.20<CR><LF>

that mean the code from BriComp needs some changes

or use the command DCFxxxx0005 instead
that will send each sample followed by a <CR><LF> instead (then no changes to the code are needed)

1.10<CR><LF>
1.20<CR><LF>
1.25<CR><LF>
1.23<CR><LF>
1.20<CR><LF>

https://tsi.com/getmedia/92d1aff6-a...8/5200_5300-Command-Set-6011697A-web?ext=.pdf
page 16-17

did also note that the shorter commands

DAFxx0005
or
DCFxx0005
can be used

also the manual is secured
so you can't copy text from it
very annoying


I have looked into a solution using
SerialCommands lib

the code from BriComp is more efficient
but will block the main loop, if other tasks needs to be done
 
BTW just in case this is causing issues:
Code:
bool SendCommandToFlowMeterGetResult(const char* s, unsigned int len) {
    elapsedMicros   timeout = 0;
    uint8_t         n       = 0;
    uint8_t         dpPos   = 0;
    uint8_t         count   = 0;
    char            c;
    bool            gotOK   = false;

    while (Serial1.peek() == '/n' || Serial1 == '/r') {
        c = Serial1.read();  //throw away /n and/or /r
    }

'/n' and '/r' should be '\n', etc...
 
did read the datasheet
and the returned readings
have the following format

1.10,1.20,1.25,1.23,1.20<CR><LF>

that mean the code from BriComp needs some changes

or use the command DCFxxxx0005 instead
that will send each sample followed by a <CR><LF> instead (then no changes to the code are needed)

1.10<CR><LF>
1.20<CR><LF>
1.25<CR><LF>
1.23<CR><LF>
1.20<CR><LF>

https://tsi.com/getmedia/92d1aff6-a...8/5200_5300-Command-Set-6011697A-web?ext=.pdf
page 16-17

did also note that the shorter commands

DAFxx0005
or
DCFxx0005
can be used

also the manual is secured
so you can't copy text from it
very annoying


I have looked into a solution using
SerialCommands lib

the code from BriComp is more efficient
but will block the main loop, if other tasks needs to be done

I don't know how you found out what model of Flowmeter he is using. I searched with google using the Flowmeter Commands without any luck.
If it is the Flowmeter you mention then Ascii commands are terminated with "OK"<CR><LF> (See extract from the manual below). My code was throwing away the <CR><LF> and just responding to the OK.
FlowMeterOKCRLF.png
 
BTW just in case this is causing issues:
Code:
bool SendCommandToFlowMeterGetResult(const char* s, unsigned int len) {
    elapsedMicros   timeout = 0;
    uint8_t         n       = 0;
    uint8_t         dpPos   = 0;
    uint8_t         count   = 0;
    char            c;
    bool            gotOK   = false;

    while (Serial1.peek() == '/n' || Serial1 == '/r') {
        c = Serial1.read();  //throw away /n and/or /r
    }

'/n' and '/r' should be '\n', etc...

Yea, that and a number of other things were wrong in the first piece of code.
The second one ignores all characters other that "0".."9", ".", "O" & "K".
 
No i dont want to actuate anything from the console, I just thought yours was doing that. What I want is for the thing to turn on and start giving me flow readings until it hits 85.0 LPM. However, when I turn your code on it does nothing. Nothing comes out on the console at all. I'm wondering if my RS232 to ttl converter is connected correctly. My pinout is VCC - 5v, Rx = pin 0, Tx = Pin 1, Gnd - 0v. On the converter itself it has a male end DB9 and it's connected to the Flowmeter by RS232 Female to USB-A right into the meter.

The Flowmeter/TTL Converter Rx should be connected to the Teensy Tx and the Flowmeter/TTL converter Tx to the Teensy Rx.
Flowmeter Connections.png
 
OK Here is version 3 of the software, making allowances for how the flowmeter is assumed to return results.
It is assumed that the flowmeter is the one highlighted above by @manicksan .
When the flowmeter is asked to return data by sending the code "DAFxx0005\r\n" (notice that there are NOW only two x's as required) it responds with
"OK"<CR><LF> before returning the result in the format "1.10,1.20,1.25,1.23,1.20>CR><LF>".

Code:
/*
    Created:	02/03/2022 12:21:52
    Version     3
*/

#define FlowMeter Serial1
#define usbSerial Serial

#define CR '\r'

uint8_t const responseTimeout = 1000;     // 1000 ms = 1 Second

bool          flowMeterSetup  = false;
bool          debug           = true;     // <<--- with this set to true a lot of screen output will be seen
                                          // an easy way to debug progress;    
float         result;

/******************************************************************
*         Response from the FlowMeter is in the format            *
*              1.10,1.20,1.25,1.23,1.20>CR><LF>                   *
*-----------------------------------------------------------------*
*          Wait until timeout or data is terminated with          *
*                with the chars "," or <CR>.                      *
*-----------------------------------------------------------------*
*    The result is placed in the global float variable "result".  *
*   Characters other than "0".."9",".","," and <CR> are ignored.  *
*******************************************************************/

bool GetFlowMeterResult() {
    elapsedMicros   timeout = 0;
    uint8_t         n = 0;
    uint8_t         dpPos = 0;
    uint8_t         count = 0;
    char            c;
    bool            done = false;

    result = 0.0;
    count = 0;

    while (timeout < responseTimeout && !done) {
        if (debug) { usbSerial.print("GetFlowMeterResult: ");  usbSerial.print(n); usbSerial.print("  "); usbSerial.print(timeout); usbSerial.print("/"); usbSerial.print(responseTimeout); usbSerial.print("  "); usbSerial.println(!done); }
        if (FlowMeter.available()) {

            c = FlowMeter.read();
            if ((c >= '0') && (c <= '9') || (c == '.')) {
                if (c == '.') {
                    dpPos = count;
                } else {
                    result = result * 10.0 + (float)(c - '0');
                    count++;
                }
            }
            done = ((c == ',') || (c == CR));
        }
    }
    done = ( done && (timeout < responseTimeout) && (count > 0));
    if (debug) { usbSerial.println(done); }
    if (done) {
        if (count > 0) {
            count -= dpPos;
            while (count > 0) {
                result /= 10.0;
                count--;
            }
        }
    }
    return done;
}

/******************************************************************
*   Confirm that the FlowMeter has returned OK in that order.     *
*              All other characters are ignored                   *
*-----------------------------------------------------------------*
*         Wait until timeout or data is terminated with           *
*                      with the chars "OK"       .                *
*******************************************************************/

bool ConfirmFlowMeterOKResponse() {
    elapsedMicros   timeout = 0;
    bool            gotOK   = false;
    bool            done    = false;
    uint8_t         n       = 0;
    char            c;

    n = 0;
    while (!(timeout >= responseTimeout || gotOK || done)) {
        if (debug) { usbSerial.print("ConfirmFlowMeterOKResponse: ");  usbSerial.print(n); usbSerial.print("  "); usbSerial.print(timeout); usbSerial.print("/"); usbSerial.print(responseTimeout); usbSerial.print("  "); usbSerial.println(!gotOK); }
        if (FlowMeter.available()) {

            c = FlowMeter.read();
            if (n == 0) {
                if (c == 'O') {
                    n++;
                }
            } else if (n == 1) {
                if (c == 'K') {
                    gotOK = true;
                } else {
                    done = true;
                }
            }
        }
    }
    if (debug) { usbSerial.println(gotOK); }
    return gotOK;
}

void setup()
{
    usbSerial.begin(9600);                             // Start USB Serial - Output to PC
    while (!Serial && millis() < 5000) {};          // wait for USB Serial to establish itself
    usbSerial.println("Setting up UART");
    FlowMeter.begin(115200);                          // Initialise Uart Port @ 115200
                                                    /*  ser = usbSerial.Serial(
                                                        port = "COM13", baudrate = 115200,
                                                        parity = usbSerial.PARITY_NONE, stopbits = usbSerial.STOPBITS_ONE,
                                                        bytesize = usbSerial.EIGHTBITS, timeout = 1)
                                                    */

                                                    //    FlowMeter.write('?\r\n');
    usbSerial.println("Sending commands to Flowmeter");
    if (debug) { usbSerial.print("    SUS\r\n"); }
    FlowMeter.print("SUS\r\n");

    if (ConfirmFlowMeterOKResponse()) {                           // was FlowMeter.write('SUS\r\n');     # Set Flow type to SLPM(Returns "OK")
        if (debug) { usbSerial.print("    SG0\r\n"); }
        FlowMeter.print("SG0\r\n");

        if (ConfirmFlowMeterOKResponse()) {                       // was FlowMeter.write('SG0\r\n');     # Set Flow Gas to Air(Returns "OK")
            if (debug) { usbSerial.print("    SSR0005\r\n"); }
            FlowMeter.print("SSR0005\r\n");

            if (ConfirmFlowMeterOKResponse()) {               // was FlowMeter.write('SSR0005\r\n'); # Set Sample Rate to 5ms(Returns "OK")
                if (debug) { usbSerial.print("    LPZ\r\n"); }
                FlowMeter.print("LPZ\r\n");
                flowMeterSetup = (ConfirmFlowMeterOKResponse());  // was FlowMeter.write('LPZ\r\n');     # Zero Low Pressure Sensor
            }
        }
    }
    delay(500);             // a delay time after setup may be required.
}

void loop()
{
    uint8_t const numReadings   = 5;
    float         total         = 0.0;
    float         avg           = 0.0;

    if (flowMeterSetup) {
        while (avg < 85.0) {
            total = 0.0;
            if (debug) { usbSerial.print("    DAFxx0005\r\n"); }
            FlowMeter.print("DAFxx0005\r\n");
            if (ConfirmFlowMeterOKResponse()) {

                for (uint8_t idx = 0; idx++; idx < numReadings) {
                    if (GetFlowMeterResult()) {
                        total += result;
                    } else {
                        usbSerial.println(F("DAFxxxx0005\r\n: Errors Getting Data from flowmeter"));
                    }
                }

            } else {
                usbSerial.println(F("Error initiating readings from flowmeter"));
            }
            avg = total / (float)numReadings;
            usbSerial.print("Flowmeter output : ");
            usbSerial.println(avg);
        }
    }
    else
    {
        usbSerial.println(F("Errors when setting up flowmeter"));
    }
    delay(1500);  //Just sit around for 1.5 seconds

}
 
This the output of the version 2 code:

Code:
Setting up UART
Sending commands to Flowmeter
    SUS
    .
Errors when setting up flowmeter
Errors when setting up flowmeter
Errors when setting up flowmeter

This is the output of the version 3 code:
Code:
Setting up UART
Sending commands to Flowmeter
    SUS
ConfirmFlowMeterOKResponse: 0  8/232  1
ConfirmFlowMeterOKResponse: 0  27/232  1
ConfirmFlowMeterOKResponse: 0  44/232  1
ConfirmFlowMeterOKResponse: 0  63/232  1
ConfirmFlowMeterOKResponse: 0  83/232  1
ConfirmFlowMeterOKResponse: 0  102/232  1
ConfirmFlowMeterOKResponse: 0  124/232  1
ConfirmFlowMeterOKResponse: 0  141/232  1
ConfirmFlowMeterOKResponse: 0  160/232  1
ConfirmFlowMeterOKResponse: 0  182/232  1
ConfirmFlowMeterOKResponse: 0  200/232  1
ConfirmFlowMeterOKResponse: 0  218/232  1
0
Errors when setting up flowmeter

When I use this smaller code (See Below) I still get no output and noticed it's not making it into the while loop almost like the serial is not available.

Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.print("?\r\n");
  while (Serial1.available()){
    s = Serial1.read();
    Serial.print(s);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

Thi is how my Flowmeter is connected for VCC I've tried 5v and 3.3v to no success and I've tried swapping the Rx and Tx just in case.
teensy.png
 
Last edited:
OK Here is version 3 of the software, making allowances for how the flowmeter is assumed to return results.
It is assumed that the flowmeter is the one highlighted above by @manicksan .
When the flowmeter is asked to return data by sending the code "DAFxx0005\r\n" (notice that there are NOW only two x's as required) it responds with
"OK"<CR><LF> before returning the result in the format "1.10,1.20,1.25,1.23,1.20>CR><LF>".

Code:
/*
    Created:	02/03/2022 12:21:52
    Version     3
*/

#define FlowMeter Serial1
#define usbSerial Serial

#define CR '\r'

uint8_t const responseTimeout = 1000;     // 1000 ms = 1 Second

bool          flowMeterSetup  = false;
bool          debug           = true;     // <<--- with this set to true a lot of screen output will be seen
                                          // an easy way to debug progress;    
float         result;

/******************************************************************
*         Response from the FlowMeter is in the format            *
*              1.10,1.20,1.25,1.23,1.20>CR><LF>                   *
*-----------------------------------------------------------------*
*          Wait until timeout or data is terminated with          *
*                with the chars "," or <CR>.                      *
*-----------------------------------------------------------------*
*    The result is placed in the global float variable "result".  *
*   Characters other than "0".."9",".","," and <CR> are ignored.  *
*******************************************************************/

bool GetFlowMeterResult() {
    elapsedMicros   timeout = 0;
    uint8_t         n = 0;
    uint8_t         dpPos = 0;
    uint8_t         count = 0;
    char            c;
    bool            done = false;

    result = 0.0;
    count = 0;

    while (timeout < responseTimeout && !done) {
        if (debug) { usbSerial.print("GetFlowMeterResult: ");  usbSerial.print(n); usbSerial.print("  "); usbSerial.print(timeout); usbSerial.print("/"); usbSerial.print(responseTimeout); usbSerial.print("  "); usbSerial.println(!done); }
        if (FlowMeter.available()) {

            c = FlowMeter.read();
            if ((c >= '0') && (c <= '9') || (c == '.')) {
                if (c == '.') {
                    dpPos = count;
                } else {
                    result = result * 10.0 + (float)(c - '0');
                    count++;
                }
            }
            done = ((c == ',') || (c == CR));
        }
    }
    done = ( done && (timeout < responseTimeout) && (count > 0));
    if (debug) { usbSerial.println(done); }
    if (done) {
        if (count > 0) {
            count -= dpPos;
            while (count > 0) {
                result /= 10.0;
                count--;
            }
        }
    }
    return done;
}

/******************************************************************
*   Confirm that the FlowMeter has returned OK in that order.     *
*              All other characters are ignored                   *
*-----------------------------------------------------------------*
*         Wait until timeout or data is terminated with           *
*                      with the chars "OK"       .                *
*******************************************************************/

bool ConfirmFlowMeterOKResponse() {
    elapsedMicros   timeout = 0;
    bool            gotOK   = false;
    bool            done    = false;
    uint8_t         n       = 0;
    char            c;

    n = 0;
    while (!(timeout >= responseTimeout || gotOK || done)) {
        if (debug) { usbSerial.print("ConfirmFlowMeterOKResponse: ");  usbSerial.print(n); usbSerial.print("  "); usbSerial.print(timeout); usbSerial.print("/"); usbSerial.print(responseTimeout); usbSerial.print("  "); usbSerial.println(!gotOK); }
        if (FlowMeter.available()) {

            c = FlowMeter.read();
            if (n == 0) {
                if (c == 'O') {
                    n++;
                }
            } else if (n == 1) {
                if (c == 'K') {
                    gotOK = true;
                } else {
                    done = true;
                }
            }
        }
    }
    if (debug) { usbSerial.println(gotOK); }
    return gotOK;
}

void setup()
{
    usbSerial.begin(9600);                             // Start USB Serial - Output to PC
    while (!Serial && millis() < 5000) {};          // wait for USB Serial to establish itself
    usbSerial.println("Setting up UART");
    FlowMeter.begin(115200);                          // Initialise Uart Port @ 115200
                                                    /*  ser = usbSerial.Serial(
                                                        port = "COM13", baudrate = 115200,
                                                        parity = usbSerial.PARITY_NONE, stopbits = usbSerial.STOPBITS_ONE,
                                                        bytesize = usbSerial.EIGHTBITS, timeout = 1)
                                                    */

                                                    //    FlowMeter.write('?\r\n');
    usbSerial.println("Sending commands to Flowmeter");
    if (debug) { usbSerial.print("    SUS\r\n"); }
    FlowMeter.print("SUS\r\n");

    if (ConfirmFlowMeterOKResponse()) {                           // was FlowMeter.write('SUS\r\n');     # Set Flow type to SLPM(Returns "OK")
        if (debug) { usbSerial.print("    SG0\r\n"); }
        FlowMeter.print("SG0\r\n");

        if (ConfirmFlowMeterOKResponse()) {                       // was FlowMeter.write('SG0\r\n');     # Set Flow Gas to Air(Returns "OK")
            if (debug) { usbSerial.print("    SSR0005\r\n"); }
            FlowMeter.print("SSR0005\r\n");

            if (ConfirmFlowMeterOKResponse()) {               // was FlowMeter.write('SSR0005\r\n'); # Set Sample Rate to 5ms(Returns "OK")
                if (debug) { usbSerial.print("    LPZ\r\n"); }
                FlowMeter.print("LPZ\r\n");
                flowMeterSetup = (ConfirmFlowMeterOKResponse());  // was FlowMeter.write('LPZ\r\n');     # Zero Low Pressure Sensor
            }
        }
    }
    delay(500);             // a delay time after setup may be required.
}

void loop()
{
    uint8_t const numReadings   = 5;
    float         total         = 0.0;
    float         avg           = 0.0;

    if (flowMeterSetup) {
        while (avg < 85.0) {
            total = 0.0;
            if (debug) { usbSerial.print("    DAFxx0005\r\n"); }
            FlowMeter.print("DAFxx0005\r\n");
            if (ConfirmFlowMeterOKResponse()) {

                for (uint8_t idx = 0; idx++; idx < numReadings) {
                    if (GetFlowMeterResult()) {
                        total += result;
                    } else {
                        usbSerial.println(F("DAFxxxx0005\r\n: Errors Getting Data from flowmeter"));
                    }
                }

            } else {
                usbSerial.println(F("Error initiating readings from flowmeter"));
            }
            avg = total / (float)numReadings;
            usbSerial.print("Flowmeter output : ");
            usbSerial.println(avg);
        }
    }
    else
    {
        usbSerial.println(F("Errors when setting up flowmeter"));
    }
    delay(1500);  //Just sit around for 1.5 seconds

}

I am still getting the same error as reply #19. I also need to use the DAFxxxx0005 command because I need to be able to use the use DAFxxLx0005 for the differential pressure reading as well down the road.
 
I'm just confused how does the Serial1 know that the sensor is on pins 0 and 1 vs being on pins 9 and 10 or any other RX TX pins
 
Serialn is mapped to Txn and Txn.
Look at the card which came with your Teensy.
Rx1 and Tx1 are Serial1 on pins 0 & 1
Rx2 and Tx2 are Serial2 on pins 9 & 10
Rx3 and Tx3 are Serial3 on pins 7 & 8
Rx4 and Tx4 are Serial4 on pins 31 & 32
Rx5 and Tx5 are Serial5 on pins 34 & 34

There is another serial port on the rear of the t3.5

The flowmeter manual states that there should only be 2 x's on the request readings command.
flowmeter readings response.png
 
I need to use the second one. You just replace reading you dont want with an x so in this usecase I want DAFxxxxx0005 and down the road want to use DAFxxxLx0005.
Screenshot 2022-03-02 095240.png
 
This the output of the version 2 code:

Code:
Setting up UART
Sending commands to Flowmeter
    SUS
    .
Errors when setting up flowmeter
Errors when setting up flowmeter
Errors when setting up flowmeter

This is the output of the version 3 code:
Code:
Setting up UART
Sending commands to Flowmeter
    SUS
ConfirmFlowMeterOKResponse: 0  8/232  1
ConfirmFlowMeterOKResponse: 0  27/232  1
ConfirmFlowMeterOKResponse: 0  44/232  1
ConfirmFlowMeterOKResponse: 0  63/232  1
ConfirmFlowMeterOKResponse: 0  83/232  1
ConfirmFlowMeterOKResponse: 0  102/232  1
ConfirmFlowMeterOKResponse: 0  124/232  1
ConfirmFlowMeterOKResponse: 0  141/232  1
ConfirmFlowMeterOKResponse: 0  160/232  1
ConfirmFlowMeterOKResponse: 0  182/232  1
ConfirmFlowMeterOKResponse: 0  200/232  1
ConfirmFlowMeterOKResponse: 0  218/232  1
0
Errors when setting up flowmeter

When I use this smaller code (See Below) I still get no output and noticed it's not making it into the while loop almost like the serial is not available.

Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.print("?\r\n");
  while (Serial1.available()){
    s = Serial1.read();
    Serial.print(s);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

Thi is how my Flowmeter is connected for VCC I've tried 5v and 3.3v to no success and I've tried swapping the Rx and Tx just in case.
View attachment 27688

That's not a very good photograph it's impossible to see where the wires go due to parallax error - the camera is not pointing straight down.
It is also impossible to see what rs232 to ttl adaptor you are using.

As for the small snippet of code, the while (Serial1.available()) is being executed but that there is no data in the Serial1 port to be collected.
You could put a delay before the while statement to allow the flowmeter to answer.

Alternatively put the while ... in loop as below.
Code:
char s;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() < 5000)) {};
  Serial1.begin(115200);
  delay(1000);
  Serial1.print("?\r\n");
}

void loop() {
  // put your main code here, to run repeatedly:
  while (Serial1.available()){
    s = Serial1.read();
    Serial.print(s);
  }

}
 
Back
Top