Arduino Mega serial in and serial out to OLED

I was pointed to this programming section by Raschemmel for my inquiry.

I searched some to find I need the Arduino Mega, but there is more info I need on what is possible with my project.
I've installed a programmable auto transmission controller in my old Toyota Supra which outputs/streams serial data from its DB9 connector at 19.2K. This data can be received by a 16x2 serial LCD to monitor its current values such as auto or manual mode, gear the transmission is in, throttle position, MPH, and RPM. The format seems to be:
M G TH SP RPM
a 2 15 30 2500

I want to use a 16x2 OLED display that has a BAUD of 9600, but I only want to display 2 of those values with the words "Mode" and "Gear" in small font and the current values (mode) "a" and (gear) "2" in large font such as this:
2 Gear Mode a

Is it possible to receive this data from the transmission controller at 19.2K BAUD through a serial input of the Arduino Mega and output specific values out to the serial OLED that runs at 9600 BAUD?

The manual of this SSv4 unit is located at http://www.latentsolutions.com/SSv4.6.pdf
The BAUD rate of the controller cannot be changed from 19.2 and the BAUD of the 16x2 serial OLEDs I have found is 9600.

I am novice with code and exactly what hardware is needed for certain projects like this, but I will figure it out if I'm guided the right direction for correct hardware to start with.

The serial info being sent out of the trans controller looks like this:

00                                               .               
1b 5b 30 3b 33 30 3b 34 37 6d 0c 0a 0d 53 75 70  .[0;30;47m...Sup
72 61 53 74 69 63 6b 20 56 65 72 73 69 6f 6e 3a  raStick Version:
20 34 2e 36 3a 20 20 50 72 65 73 73 20 31 20 66   4.6:  Press 1 f
6f 72 20 75 73 65 72 20 63 6f 6e 66 69 67 0a 0d  or user config..
47 65 61 72 20 43 68 61 6e 67 65 20 1b 5b 30 3b  Gear Change .[0;
33 37 3b 34 30 6d 31 1b 5b 30 3b 33 30 3b 34 37  37;40m1.[0;30;47
6d 20 31 38 31 32 31 30 20 20 20 30 20 20 20 0a  m 181210   0   .
0a 0d 4d 20 47 20 54 48 20 53 50 44 20 52 50 4d  ..M G TH SPD RPM
0a 0d 4d 20 31 20 33 20 20 30 20 20 20 30 20 20  ..M 1 3  0   0  
20 0d 4c 6f 63 6b 75 70 20 43 68 61 6e 67 65 20   .Lockup Change 
31 20 33 20 20 30 20 20 20 30 20 20 20 0a 0d 6d  1 3  0   0   ..m
20 31 20 33 20 20 30 20 20 20 30 20 20 20 0d 6d   1 3  0   0   .m
20 31 20 32 20 20 30 20 20 20 30 20 20 20 0d 6d   1 2  0   0   .m
20 31 20 33 20 20 30 20 20 20 30 20 20 20 0d 6d   1 3  0   0   .m
20 31 20 33 20 20 30 20 20 20 30 20 20 20 0d 6d   1 3  0   0   .m
20 31 20 33 20 20 30 20 20 20 30 20 20 20         1 3  0   0     
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 32 20 20 30 20 20 20 30 20 20 20  .m 1 2  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
                                                                 
0d 6d 20 31 20 32 20 20 30 20 20 20 30 20 20 20  .m 1 2  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
                                                                 
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 32 20 20 30 20 20 20 30 20 20 20  .m 1 2  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
                                                                 
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 32 20 20 30 20 20 20 30 20 20 20  .m 1 2  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
0d 6d 20 31 20 33 20 20 30 20 20 20 30 20 20 20  .m 1 3  0   0   
                                                                 
0d 6d 20 31 20 32 20 20 30 20 20 20 30 20 20 20  .m 1 2  0   0   
0a 0d 4d 20 47 20 54 48 20 53 50 44 20 52 50 4d  ..M G TH SPD RPM
0a 0d 61 20 31 20 33 20 20 30 20 20 20 30 20 20  ..a 1 3  0   0  
20 0d 61 20 31 20 33 20 20 30 20 20 20 30 20 20   .a 1 3  0   0  
20 0d 61 20 31 20 33 20 20 30 20 20 20 30 20 20   .a 1 3  0   0

Thank you for any info,
Chris Robertson

The serial info being sent out of the trans controller looks like this:

You have some code that proves that?

The MEGA2560 has 3 extra hardware serial ports. Leave RX and TX (pins 0 and 1) alone so you can use them to debug on the PC through USB. RX1 through TX3 are pins 14-19, you can use 1 set for reading the Supra and another to feed the OLED. They can each have their own speed.

Here I set up a MEGA using Serial (RX/TX) to USB and Serial1 (RX1/TX1) to an audio player:

void setup( void )
{
  Serial.begin( 115200 );
  Serial1.begin( 115200 );
  pinMode( blinkPin, OUTPUT ); // should default LOW
  Serial.println( "\nStartup" );
}

I can read the player as Serial1.read() and the PC as Serial.read().

PaulS:

The serial info being sent out of the trans controller looks like this:

You have some code that proves that?

Thanks for the reply. This output from trans controller was captured with the Termite program reading COM1 port on my laptop.

GoForSmoke:
The MEGA2560 has 3 extra hardware serial ports. Leave RX and TX (pins 0 and 1) alone so you can use them to debug on the PC through USB. RX1 through TX3 are pins 14-19, you can use 1 set for reading the Supra and another to feed the OLED. They can each have their own speed.

Here I set up a MEGA using Serial (RX/TX) to USB and Serial1 (RX1/TX1) to an audio player:

void setup( void )

{
 Serial.begin( 115200 );
 Serial1.begin( 115200 );
 pinMode( blinkPin, OUTPUT ); // should default LOW
 Serial.println( "\nStartup" );
}




I can read the player as Serial1.read() and the PC as Serial.read().

Thank you very much for the reply. It is great to know I can use different BAUD rates for each serial line on the Mega. This may broaden my project to allow connecting a second serial input from my O2 sensor controller in the car and switch from displaying transmission info to displaying O2 sensor info, correct?

Yup. The MEGA2560 has 4 serial ports.

(marketing commercial mode: ON) But Wait! There's More!
You can use any two digital pins and the SoftwareSerial library to set up another serial channel and so forth.

One BIG make sure you do with all of these --- connect ALL the grounds. Serial is 2 data wires and GROUND. Without the ground you can fry the hardware and even if you don't, the signals will not be reliable.

Whoa! Hold the Bus! I almost let this go by!

That DB9 serial is about 100% likely to not be Arduino safe 5V but 12V (+6 and -6 which will smoke your board!).

You need to level-shift those pins!

(marketing commercial mode: ON) But Wait! There's More!
You can use any two digital pins and the SoftwareSerial library to set up another serial channel and so forth.

Any two pins? Not on a Mega. Or any other Arduino for that matter. You can not, for instance, use the hardware serial pins.

Okay, I didn't think of that because I wouldn't think of doing that. Good thing that wasn't code!

But even on an UNO with only 1 serial port it's possible to use SoftwareSerial. I've done it.

Thank you guys for the previous relies. It’s was a long few days trying to learn how to code and trying to make this stuff work together, with some flaws.
I ordered the Sainsmart Mega2560 and a serial OLED for the transmission display project. I was finally able to figure out how to add code for the Gear and Mode label positions while also learning to mix font sizes. I had a coworker try to help me with this, but he wrote up some code for to buffer the data Serial2 (19.2 baud Transmission controller) to send to Serial1 (19.2 baud OLED display). This seems to work, but not quite right. Can someone offer help on correction to the Arduino code to make this work correctly?
The first post shows captured data from the output of serial data from transmission controller. The data shows some apparent carriage return (0d) and line feed (0a) sent from the controller with the current values. I only need to display the Mode “m”, “M”, or “a”, “A” and the Gear 1, 2, 3, 4.
Here is a video of the display working with the code below: Serial to OLED issue - YouTube
“&& buffer[1] == 20” he added in belief it would do something with the spaces, but this caused no serial communication. Once commented out serial data began to output.

#define HOME (char) 1           // Moveto character position 0.
#define FLARGER (char) 2        // Increase font size.
#define FRESET (char) 3        // Reset font to default/small. 
#define CLS (char) 12          // Clear screen, moveto 0.
#define MOVETO (char) 16       // Position instruction
#define PPE (char) (19 + 64)   //Arrows
#define GEARL (char) (0 + 64)    // Position of Gear data field
#define MODEL (char) (7 + 64)   //Position of Mode data field
#define LABEL (char) (3 + 64)  //"Gear" label position
#define LABEL2 (char) (9 + 64)  //"Mode" label position
#define RTALIGN (char) 18      //Ctrl-R right-align instruction
#define FSEGMENT (char) 19     //*Change Gear font to 7-SEGMENT
#define FBIG (char) 20   //*Change font to TEXT style for splash screen

//------------------------------------------------------------
//Setup
//------------------------------------------------------------
void setup() {
  // initialize both serial ports:
  Serial2.begin(19200);
  Serial1.begin(19200);

Serial1.write (CLS);
  delay(50);
  Serial1.write (FRESET);
  Serial1.write (MOVETO);
  Serial1.write (LABEL);
  Serial1.write ("Gear");
  Serial1.write (MOVETO);
  Serial1.write (PPE);
  Serial1.write ("<---  --->");   
  Serial1.write (MOVETO);
  Serial1.write (LABEL2);
  Serial1.write ("Mode");  
  Serial1.write (FLARGER);
  Serial1.write (FLARGER);
  Serial1.write (FLARGER);
  delay (800);


}

//-------------------------------------------------------------
//Start Loop
//-------------------------------------------------------------

void loop() {
  int i = 0;
  char buffer[5];

  // read from port 0, send to port 1:
  if(Serial2.available()) {
    delay(30); // allows buffer to fill

    while(Serial2.available() && i < 4) {
      buffer[i++] = Serial2.read();
    }

    buffer[i++]='\0';
  }

  // did we receive data?  If so, try to display it.
  
  if(i > 0 /*&& buffer[1] == 20*/){
  
    Serial1.write(MOVETO); 
    Serial1.write(GEARL);
    Serial1.write(buffer[3]);
    Serial1.write(MOVETO);
    Serial1.write(MODE);
    Serial1.write(buffer[1]);
  } 
}

Thanks for any help.

Rewrite everything in loop().
That "delay() and assume the transmission is in" is really lame.
You should be reading the data for delimiters/markers of some kind and operating on those.

Thanks,
I am very novice on code. I have searched and searched for days to find good examples for this type of project and the only thing I have found, and made work, is getting serial communication from serial2 to the display on serial1. I am a quick study , but I am lost on which direction to go to figure out how to write this code.

See if this helps, especially the State Machine part:

In this blog Nick shows how to do multiple things at once, explaining blocking and non-blocking code in the process:

What you need to do is not a whole lot more than the State Machine example. You may need to look for more than single characters but the principle is the same and btw, the extent of what you are doing does qualify as "work" and not some quick little bit of code. Spend time planning every step you need to do before you write a line.

This is not lame, lol. Thank you for the link. This is something I never found in my 6 days of searches....

That was great. Thanks again for the link. What exactly would I do if I wanted to take only the first digit “4” of a number such as “4321” and print only that number?

if ( charJustRead == ‘4’ ) // that’s the one officer!
{
// arrest him!
}

My biggest concern would be getting the ‘right’ 4 out of the stream. I saw the dump you posted and there is a definite pattern with certain delimiter chars. After all, it is meant to be read and used. Have you gone through the data and defined for yourself what rules it works by?

A real simple data stream will always have the data in the same pattern but others get trickier. It looks to me like you should look of “.m” and then space digit space digit.

With text data you are reading ASCII values. Any text char in single quotes is the value.
char x = ‘0’; // now x == 48 == ‘0’
You can say space==32 and set up a var just for it or you can code ’ ’ and the code will be easier to read.
If you read a digit the value will be from ‘0’ to ‘9’, you subtract ‘0’ from it and you have the value.

If you #include <ctypes.h>
http://www.nongnu.org/avr-libc/user-manual/group__ctype.html

Then you get these functions below which mostly return TRUE or FALSE.

<ctype.h>: Character Operations
Character classification routines

These functions perform character classification. They return true or false status depending whether the character passed to the function falls into the function’s classification (i.e. isdigit() returns true if its argument is any value ‘0’ though ‘9’, inclusive). If the input is not an unsigned char value, all of this function return false.
int isalnum (int __c)
int isalpha (int __c)
int isascii (int __c)
int isblank (int __c)
int iscntrl (int __c)
int isdigit (int __c)
int isgraph (int __c)
int islower (int __c)
int isprint (int __c)
int ispunct (int __c)
int isspace (int __c)
int isupper (int __c)
int isxdigit (int __c)
Character convertion routines

This realization permits all possible values of integer argument. The toascii() function clears all highest bits. The tolower() and toupper() functions return an input argument as is, if it is not an unsigned char value.
int toascii (int __c)
int tolower (int __c)
int toupper (int __c)

I hope this helps.

What exactly would I do if I wanted to take only the first digit "4" of a number such as "4321" and print only that number?

Take it from where? What should happen to the rest of the characters?