Plucking portions of data from serial stream to display on LCD

I envy your knowledge. It would be nice not to feel like like I have a mental blindfold on while thrashing around like an idiot. There just seems to be so much to learn and so many concepts it's overwhelming.

Keep at it for 32 years. I doubt you'll still feel like an idiot.

I don't know. Some days...

I've had a few of those "what the hell was I thinking?" days myself. Not nearly as stressful as first learning a language, though. At least, I can now recognize a mistake when I make it.

Ok, with that I am able to see the information but of course, it is strewn across the LCD and not placed in any certain position. Also, the LCD has all pixels lit. The information flashes over the lit areas and then it returns to an all on state.

So, with that said any pointers on which direction to head when it comes to actually pulling out the ten character fields F 8,992.00 in my above example?

Thanks again.

mancow:
If you know that you want to read 20 characters, you need to either read them as they become available, or wait for them to become available, and then read them all at once. The second is simplest.

The characters look like all bits on because you don't have the contrast set properly.

No, I thought that too but that's not it. The activity is the same regardless of the setting of the trim pot on the serial backpack board, only it's in proportion to whatever the setting is.

**edit

It's just overrunning the LCD. I stripped things down to the bare basics, took out the volume control code etc... and am focusing on the display activity. I am sending test codes to it from a serial program and it's printing the text fine now because the test data is matching the constraints set in the code.

Now, I need to figure out how to strip off the unwanted data and only display the portions I want to see from the radio.

I'm probably just babbling and spamming the board here so I should probably just keep quiet until I figure something out useful I suppose.

Now, I need to figure out how to strip off the unwanted data and only display the portions I want to see from the radio.

And your current code looks like?

I had the forum set to the quick reply and didn't see the # function earlier.

As for the code, well I really don't have anything other to work with than what you posted earlier.

     char buffer[21];

     while(Serial.available() < 20)
     {
        // Do nothing
     }

     for (i=0;i<20;i++)
     {
         buffer[i] = Serial.read();
         buffer[i+1] = '\0';
     }     
     lcd.print(buffer);

I saved off all my other working control code and have been starting with a very basic blank sketch based on this except I'm using Serial.print instead of lcd so I don't have to mess with LCD stuff right now. I've been trying to read as much as possible and have like 15 tabs of different references and various web pages up but I'm still trying to get the basic concepts.

Using the code above it will of course echo back to the serial the 20 hex characters I send to it. I am trying to figure out the next small step of how to work with the data it sends back. I am trying to figure out how to send back only portions of what is received such as bytes 5 through 10 or something similar.

Using the code above it will of course echo back to the serial the 20 hex characters I send to it. I am trying to figure out the next small step of how to work with the data it sends back. I am trying to figure out how to send back only portions of what is received such as bytes 5 through 10 or something similar.

Arrays are arrays. Doesn't matter if they contain chars, ints, floats, pointers, or structs. If you want elements 5 to 10 from one array in another one, create the 2nd array, and copy the data.

char importantStuff[10];
for(int i=5, j=0; i<=10; i++, j++)
{
   importantStuff[j] = buffer[i]; // Copy a character
   importantStuff[j+1] = '\0'; // Keep NULL terminated
}
Serial.print("importantStuff: [");
Serial.print(importantStuff);
Serial.println("]");

If you are not sure where the data of interest is (5 to 10 may not be quite right), you can use strchr() to find a character in a string (a comma, maybe) or strstr() to find a string in a string ("LED=", maybe).

Thank you for the information. I swear I have been searching with every permutation you can think of in Google and have probably read through or skimmed over a hundred web pages and I never once saw a straight forward reference like this anywhere.

It works great after a small bit of adjustment. Thanks again!

I was getting closer to the answer. I was exploring the for loops but I didn't think of intertwining the two strings like that in one loop. I was trying to somehow basically do a sub loop.

It's great to have a place like this to get help.

also:

you just blew my mind with this

Serial.print("importantStuff: [");
Serial.print(importantStuff);
Serial.println("]");

I didn't know you could insert statements within statements like that across lines. Wild...

This is what I have so far. I know it's ugly. :blush:

My question is why the outgoing serial control portion at the top does not work after adding in the bottom portion that deals with the LCD. If I comment out the :

while (Serial.available() <20);
through the...
lcd.print(freqLine);

Button and volume controls will then transmit their corresponding codes appropriately.

// these constants won't change:
const int sensorMin = 0;      // volume minimum
const int sensorMax = 1000; // volume maximum  orig setting 600 // include the library code:
#include "Wire.h"
#include "LiquidCrystal.h"  // initialize the library with the numbers of the interface pins LiquidCrystal lcd(0);

#define INPIN1 2  //Arrow up button
#define INPIN2 3  //Arrow down button
int state1 = HIGH;
int state2 = HIGH;
int previousvolume = 0;
int incomingByte = 0;
char freqLine[10];
LiquidCrystal lcd(0);

void setup() {

  lcd.begin(20, 4);
  Serial.begin(9600);
  UCSR0C = UCSR0C | B00111000; // modded to change to odd parity so it matches the Micom standard of 8-odd-1
  pinMode(INPIN1, INPUT);  //arrow up 
  pinMode(INPIN2, INPUT); //arrow down
}
void loop() {

  // read the volume pot 
  int sensorReading = analogRead(A0);   // map the sensor range to a range of eight options across the volume range:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 15);
  int volume = range;

  //buttonState = digitalRead(buttonPin); // read arrow up button state

    delay(10); // debounces switches
  int val1 = digitalRead(INPIN1);
  int val2 = digitalRead(INPIN2);

  {
    if (val1 == HIGH)
    {
      byte UPBUTTON[10] = {
        0x24,0x05,0x18,0x36,0xFE,0x7B,0xEF,0x01,0xE0,0x03 }; // up button command
      Serial.write(UPBUTTON, 10); // will write the array of bytes to the serial port in raw hex form (length 10)
      delay(20);
      byte RELEASEBUTTON[10] = {
        0x24,0x05,0x18,0x36,0xFF,0x7B,0xEF,0x01,0xE1,0x03 }; // release button command
      Serial.write(RELEASEBUTTON, 10); // will write the array of bytes to the serial port in raw hex form (length 10)
      delay(50);

    }
    if (val2 == HIGH)
    {
      byte DWNBUTTON[10] = {
        0x24,0x05,0x18,0x36,0xDF,0x7B,0xEF,0x01,0xC1,0x03                              } // up button command
      ;
      Serial.write(DWNBUTTON, 10); // will write the array of bytes to the serial port in raw hex form (length 10)
      delay(20);
      byte RELEASEBUTTON[10] = {
        0x24,0x05,0x18,0x36,0xFF,0x7B,0xEF,0x01,0xE1,0x03                              } // release button command
      ;
      Serial.write(RELEASEBUTTON, 10); // will write the array of bytes to the serial port in raw hex form (length 10)
      delay(50);
    }
  }

  // Volume control section starts below
  if (previousvolume != range){
    switch (range) { 

    case 0:    // lowest volume level (muted)
      {
        byte vol0[8] = {
          0x24,0x03,0x18,0x2B,0x00,0x00,0x6A,0x03                                        } // volume level 0 in hex
        ;
        Serial.write(vol0, 8); 
        previousvolume = 0;
      }
      break;

    case 1:   // 5
      {
        byte vol10[8] = {
          0x24,0x03,0x18,0x2B,0x05,0x00,0x6F,0x03                                        } // volume level 05 in hex
        ;
        Serial.write(vol10, 8); 
        previousvolume = 1;
      }
      break;

    case 2:
      // 6
      {
        byte vol5[8] = {
          0x24,0x03,0x18,0x2B,0x06,0x00,0x70,0x03                                        } // volume level 06 in hex
        ;
        Serial.write(vol5, 8); 
        previousvolume = 2;
      }
      break;


    case 3:    // 7
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x07,0x00,0x71,0x03                                        } // volume level 07 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = range;
      }
      break;

    case 4:    // 8
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x08,0x00,0x72,0x03                                        } // volume level 08 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 4;
      }
      break;

    case 5:    // 9
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x09,0x00,0x73,0x03                                        } // volume level 09 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 5;
      }
      break;

    case 6:    // 10
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x10,0x00,0x7A,0x03                                        } // volume level 10 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 6;
      }
      break;

    case 7:    // 12
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x12,0x00,0x7C,0X03                                        } // volume level 12 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 7;
      }
      break;

    case 8:    // 14
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x14,0x00,0x7E,0x03                                        } // volume level 14 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 8;
      }
      break;

    case 9:    // 16
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x16,0x00,0x80,0x03                                        } // volume level 16 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 9;
      }
      break;

    case 10:    // 18
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x20,0x00,0x8A,0x03                                        } // volume level 18 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 10;
      }
      break;

    case 11:    // 25
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x25,0x00,0x8F,0x03                                        } // volume level 25 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 11;
      }
      break;

    case 12:    // 30
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x30,0x00,0x9A,0x03                                        } // volume level 30 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 12;
      }
      break;

    case 13:    // 40
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x40,0x00,0xAA,0x03                                        } // volume level 40 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 13;
      }
      break;

    case 14:    // 90
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0x90,0x00,0xFA,0x03                                        } // volume level 90 in hex
        ;
        Serial.write(vol20, 8); 
        previousvolume = 14;
      }
      break;

    case 15:    // 100
      {
        byte vol20[8] = {
          0x24,0x03,0x18,0x2B,0xB0,0x00,0x1A,0x03                                        } // volume level B0 in hex as FF is ridiculous!
        ;
        Serial.write(vol20, 8); 
        previousvolume = 15;
      }
      break;
    }
  }



  char buffer[20];
  if (Serial.available() <20);
  {
    // Do nothing
  }
  while (Serial.available() <20);
  int i;
  for (i=0;i<20;i++)
  {
    buffer[i] = Serial.read();
    buffer[i+1] = '\0';
  }
  char freqArray[10];
  for(int i=7, j=0; i<=17; i++, j++)
  {
    lcd.setCursor(0, 1);
    freqLine[j] = buffer[i]; 
    freqLine[j+1] = '\0'; // Keep NULL terminated
  }
  
  lcd.print(freqLine);

}

Thanks again.

The various arrays do not take up less space because they are local. You should consider making them global arrays.

You should consider removing the useless { and } where they occur. They scream clueless. Of course, the tricky part is determining which ones are needed, which ones are optional, and which ones are useless.

{ <-- Useless
if (val1 == HIGH)
{ <-- Optional
byte UPBUTTON[10] = { <-- Necessary

If I comment out the :

while (Serial.available() <20);
through the...
lcd.print(freqLine);

The while() loop will wait for 20 characters to arrive. That's probably not what you want to do. More likely, you want to do something only if there are at least to characters ready to be read. Blocking waiting for them may be the source of your problem.

Since you check for serial data on every pass through loop, I am sure that it is the blocking wait that is killing you.

Oh, I see what you mean. I had been throwing around { } like a madman. I went through and cleaned up a ton of them then made the volume arrays global at the top and compressed everything down. It's so much cleaner now and allowed me to see quite a few glaring errors I was unable to clearly see before.

I still need to figure out the "broken" serial issue but this has been a tremendous help so far.

Thanks once again!

I'm having synchronization issues.

The data packets always start with 0x24. Checksum second to the last right before the 0x03. They always end with 0x03. However, there is often a 0x03 in the middle somewhere.

The length of the data packet is indicated by the byte at position 1 right after the start of line (less the checksum and end of line) so we could just factor two less at all times.

Checksum is sum of everything less the checksum itself of course and the end of line marker 03. I'm thinking I could forego any checksumming since the probability of errors is very low.

I've been trying to figure out a reliable way to flag for start of line 0x24, look to byte position 1 and then read forward to the appropriate position where the 0x03 end of line marker should be. If it's present then go forward and process the information through the FOR loops and distill out the interesting data then send that to the LCD.

Something similar to : 24 08 03 48 45 4C 4C 4F A2 03

24 is start of line
08 is length (less the checksum and the end of line marker 03)
03 (if this is 03 it should be placed at LCD line 0,1) (if it's 04 then place the data received on LCD line 0,2)
48 45 4C 4C 4F displays "hello"
A2 is checksum
03 is end of data packet

As it is now without any packet marker discrimination or accountability for varying packet length from packets destined for other display areas I'm getting garbage at the front and back as well as the interesting data being shifted around on the LCD with each incoming packet.

I'm at a loss as to how to begin to write something to handle this.

Thanks for reading.

Read the serial stream until you find a 24.
Wait for a byte to be available.
Read the byte, which will tell you how many interesting bytes are coming.
Wait until that number of bytes is available (or until too much time has elapsed).
Read the n interesting bytes. The nth interesting byte should be 0x03. If it is, you got, and can use, and good packet. If not, disregard that packet, and start over, looking for a 24.

I found that the device is padding the data at times before and after the packets depending on how I'm interfacing to it. I kept wondering how such basic concepts didn't seem to work. I kept seeing garbage intermixed and was about to beat my head against the desk.

Thanks for your patience with all the dumb questions.

Edited to disregard erroneous info...

PaulS:
Read the serial stream until you find a 24.
Wait for a byte to be available.
Read the byte, which will tell you how many interesting bytes are coming.
Wait until that number of bytes is available (or until too much time has elapsed).
Read the n interesting bytes. The nth interesting byte should be 0x03. If it is, you got, and can use, and good packet. If not, disregard that packet, and start over, looking for a 24.

I'm basically stuck at this point:

Wait until that number of bytes is available (or until too much time has elapsed).
Read the n interesting bytes.

The rest makes sense to me but I'm a bit lost as to what way to use the length byte determine how much to read.