learning and lost.. trying to process fast serial data

Hi everyone. This is my first post. I've started reading a book on Arduino C programming. I'm not a stranger to electronics at all, and have familiarity with serveral scripting languages like PHP, Powershell, Java... I do some work in SmartThings home automation as well which is Groovy based. Anyway, suffice to say I'm no expert programmer but I do have some experience.

What I'm trying to do is read a constant stream of serial data coming from my car's oxygen sensor control box which operates on serial rs232 at 19200 baud, n81. The data coming out of it is what the lambda value is (how much air to fuel in the exhaust) and the readiness state and error state. The stream looks like this.

1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors1.770 Ready No-errors

For now I am just wanting the 1.770 part. It could be anything from 1.770 to 0.700. The text stuff I honestly CARE about, but not right now. In the future (and you can see it somewhat in my code) I would just do something like set the status of an LED just to represent that the data is ok and there aren't any errors.

What I'm seeing right now is if I just paste 1.770 Ready No-errors into the serial monitor, I see it perfect on the quad alphanumeric display. It was a pain to get it to show the decimals right... If I paste a long stream like above, or more importantly plug it in, I see randomly placed zeros, 7's, decimals, ones, etc.... If I paste the above into the serial monitor I see basically the same behavior. I can paste just number in all day long and it seems to be right, but something with the text I guess is causing me grief. Anyway, here's the code. Any help is really appreciated.

// reads serial data and puts it on the adafruit quad alpha display over i2c


#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();

// setup the variables
char incoming;
char displaybuffer[4];
int i=0;
boolean d[4]={false,false,false,false};
boolean readystatus= false;

void setup() {
  pinMode(13, OUTPUT); // turn off
  digitalWrite(13,LOW); // that stupid onboard LED
  Serial.begin(19200);  // set our USB baud rate
  Serial1.begin(19200); // set the TTL to serial baud rate for COM1
  alpha4.begin(0x70);  // pass in the address of the i2c alpha display
  alpha4.setBrightness(1); // set its brightness low
  alpha4.writeDigitRaw(0, 0x7FFF); // test character 1 full on
  alpha4.writeDigitRaw(1, 0x7FFF); // test character 2 full on
  alpha4.writeDigitRaw(2, 0x7FFF); // test character 3 full on
  alpha4.writeDigitRaw(3, 0x7FFF); // test character 4 full on
  alpha4.writeDisplay(); // light em up now
  delay(100); // wait a bit
  alpha4.clear(); // clear out the display
  alpha4.writeDisplay(); 
}

void loop() {
  i = 0; // reset the index to capture new data
  readystatus=false;
  while (i<=3) {
  while (! Serial.available()) return;
    incoming = Serial.read();
    // first lets deal with o2 values. grab the numbers first
    if ((incoming >= 48) and (incoming <= 57)) {
      displaybuffer[i]=incoming;
      d[i]=false;
      Serial.write("INDEX: "); Serial.println(i);
      Serial.write("BUFFER: "); Serial.println(displaybuffer[i]);
      i=i+1;
    }
    // do we need to set the decimal place?
    if (incoming == 46) {
      i=i-1;
      d[i]=true;
      //Serial.write("INDEX: "); Serial.println(i);
      //Serial.write("BUFFER: "); Serial.println(displaybuffer[i]);
      Serial.write("DECIMAL BOOL: "); Serial.println(d[i]);
      i=i+1;
    }
    // do something with spaces
    if (incoming == 32) {
    }
    // do something with the s character
    if (incoming == 115) {
    }
    /* // do something with text
    if ((incoming >= 65) and (incoming <= 126)) {
      Serial.write(incoming);
      if (incoming == 'R') {
        readystatus=true;
        Serial.write("READY STATE: "); Serial.println(readystatus);
      } else {
        readystatus=false;
        Serial.write("READY STATE: "); Serial.println(readystatus);
      }
    }*/
  dispalpha();
  }

}


void dispalpha() {
  //set every digit to the buffer
  alpha4.writeDigitAscii(0, displaybuffer[0],d[0]);
  alpha4.writeDigitAscii(1, displaybuffer[1],d[1]);
  alpha4.writeDigitAscii(2, displaybuffer[2],d[2]);
  alpha4.writeDigitAscii(3, displaybuffer[3],d[3]);
  alpha4.writeDisplay();
  if (readystatus = true) {
    digitalWrite(13,HIGH); // Set arduino status LED on
  } else {
    digitalWrite(13,LOW); // Set arduino status LED off
  }
}

void debugging() {
    Serial.println("INDEX: "); Serial.write(i);
    Serial.println("BUFFER: "); Serial.write(displaybuffer[i]);
    Serial.println("DECIMAL BOOL: "); Serial.write(d[i]);
}

This might help.
Serial Input Basics

As well as what @groundfungus has suggested you should start with a program that does nothing but receive the data and display it on the Serial Monitor.

When that works you can then extend it to include other stuff.

...R

Return to where?

while (! Serial.available()) return;

What happens when you run this

void setup() {
  pinMode(13, OUTPUT); // turn off
  digitalWrite(13,LOW); // that stupid onboard LED
  
  Serial.begin(19200);  // set our USB baud rate
  Serial1.begin(19200); // set the TTL to serial baud rate for COM1
}

void loop() {
  if (Serial1.available() > 0) {              // Something to read from sensor?
    char inChar = Serial1.peek();             // Peek at the data
    if ((inChar >= '0') && (inChar <= '9')){  // Value an ASCII number?
      while (Serial1.available() < 5){};      // Wait until at least 5 chars arrive
      float oxy = Serial1.parseFloat();       // Read the stream into a float
      Serial.print(oxy,3);                    // Print to serial monitor (3 decimal places)
    }
    else {
      Serial1.read();                         // Not a number so throw value away
    }
  }
}

Riva:
Return to where?

while (! Serial.available()) return;

To main().

  pinMode(13, OUTPUT); // turn off
  digitalWrite(13,LOW); // that stupid onboard LED

Why are you doing this? The "stupid" onboard LED is disabled by default. The pin is set to input by default.

oqibidipo:
To main().

Hmmm. What happens when main() terminates? :slight_smile:

Hmmm. What happens when main() terminates?

The return to main happens in the infinite while loop that calls loop().

aarg:

  pinMode(13, OUTPUT); // turn off

digitalWrite(13,LOW); // that stupid onboard LED




Why are you doing this? The "stupid" onboard LED is disabled by default. The pin is set to input by default.

That part is OK. The onboard LED is driven by an op-amp, and if pin 13 is left as input it might light up.

aarg:

  pinMode(13, OUTPUT); // turn off

digitalWrite(13,LOW); // that stupid onboard LED




Why are you doing this? The "stupid" onboard LED is disabled by default. The pin is set to input by default.

I find the onboard LED stays on on my Mega boards unless you explicitly turn it off. IIRC it's fine on all other Arduinos.

PaulS:
The return to main happens in the infinite while loop that calls loop().

My question was, what happens when you get there? :slight_smile:

My question was, what happens when you get there?

main() includes (something like):

   while(true)
   {
      loop();
   }

If there is a return statement in loop(), control transfers to the next statement after the function call. So, the while condition is evaluated, to decide whether to execute the body of the statement. Since the condition is always true, loop() gets called again.

I can't tell if you are serious, or just trolling, in this thread.

PaulS:
main() includes (something like):

   while(true)

{
      loop();
  }



If there is a return statement in loop(), control transfers to the next statement after the function call. So, the while condition is evaluated, to decide whether to execute the body of the statement. Since the condition is always true, loop() gets called again.

I can't tell if you are serious, or just trolling, in this thread.

Serious. I see now that an exit from loop() results in a continuation of the while() loop. Although that loop is inside main, the while loop ensures that there can never be an exit from main. But I never have seen any code that did this before. That's why I'm commenting...

To the OP
The problem is in assigning char and evaluating int.
Read your PM for details.

Vaclav:
Read your PM for details.

To @Vaclav, please post your response where everyone can benefit.

...R

Robin2:
To @Vaclav, please post your response where everyone can benefit.

...R

Robin2:
To @Vaclav, please post your response where everyone can benefit.

...R

Sorry. again. I am not going to have my code scrutinized here.

Besides - what else you have to know about the issue?
This should be pretty clear if you check the posted OP code.

The problem is in assigning char and evaluating int.

Sorry. again. I am not going to have my code scrutinized here.

It's called peer-group review, Vaclav. If there is nothing wrong with your code, you have nothing to worry about.

There is nothing to review, the code is same as OP.

Judging from this thread so far "peers" are already nitpicking on irrelevant stuff, so why would I value their review anyway.

It may be hard to swallow, but my position is a result of past experiences with this group.

Vaclav:
It may be hard to swallow, but my position is a result of past experiences with this group.

strangely, I have not had any adverse experience with all the stuff I have posted.

...R

Robin2:
As well as what @groundfungus has suggested you should start with a program that does nothing but receive the data and display it on the Serial Monitor.

When that works you can then extend it to include other stuff.

...R

I got that part down but the problem I had was processing decimals because the adafruit library for that quad alpha display doesn't process a period, you have to give whichever place requires the decimal a true false value to turn it on or off so some processing is required. I read your post about STRTOK and that looks like the best way to go about this perhaps?