Pages: [1] 2   Go Down
Author Topic: Can't figure out how to endlessly feed text to arduino for display on LCD  (Read 1450 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to send a continuous feed of messages, each message about 200 chars, to the arduino, then display them one at a time, scrolling them off the screen before the next one appears.  At first, it was displaying only 1 or 2 messages before it stopped.  I increased my RX_BUFFER_SIZE in HardwareSerial.cpp to 1024, which has enabled me to now display closer to 15 messages, but it still stops.  How do I get past the stopping part and have the messages continuously to display on the LCD?

I've tried Serial.flush, Serial.end followed by another Serial.begin, I've tried doing things with the rx buffer head and tail, etc.  None of it has enabled me to achieve the non-stop display of messages I'm looking for.

Any help would be greatly appreciated?

Thanks,
Tim
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You probably have to save them in an array but without seeing your code (Hint smiley) it's hard to say.

______
Rob

Logged

Rob Gray aka the GRAYnomad www.robgray.com

Copenhagen / Denmark
Offline Offline
Edison Member
*
Karma: 5
Posts: 2360
Do it !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Does your messages come from a PC ?

If so then i tink it would be better to implement some kind of flow control, where your Arduino will signal to the PC "hey i'm ready for the next message"
If you just keep sending a stream of messages from the PC you will sooner or later run into memory issues on Arduino.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the replies.

Does your messages come from a PC ?
If so then i tink it would be better to implement some kind of flow control, where your Arduino will signal to the PC "hey i'm ready for the next message"
If you just keep sending a stream of messages from the PC you will sooner or later run into memory issues on Arduino.

I get what you're saying about memory and flow control.  I'm trying to figure out exactly what happens when flow control is implemented that allows you to continuously take in the next message.  In that flow control process, something is reset/cleared (eg. rx buffer head & tail, pointer(s), etc.)  Since I don't care if a message is lost or overwritten in the buffer once it has been written to the LCD, I either want to keep a continuous FIFO process of writing a message to the LCD and, if the buffer is full, reading in a new message to the buffer which overwrites the one that has been displayed or simply resetting the buffer each time a message is taken in and displayed so that, basically, the buffer only really holds one message at a time.

You probably have to save them in an array but without seeing your code (Hint smiley) it's hard to say.

Unfortunately, I have many different version of the code, none of which have worked.  At the moment, I'm trying to get at the underlying process of what I'd like to achieve and then start from there.  The basic outline, though, seems to be one of these two:

read a number of strings into the buffer -> display them FIFO on the LCD -> allow just-displayed message to be overwritten by new string taken in, which becomes the last string at the end of the queue

or

read in a single string -> display it on the LCD -> reset the buffer -> take in next string

Hope this makes sense.

Thanks again,
Tim
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This seems simple enough unless I don't grasp the idea.

As you say have a FIFO of strings and print them one at a time to the LCD.

As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem.

If this is not the case then you will have issues, and flow control won't help.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Copenhagen / Denmark
Offline Offline
Edison Member
*
Karma: 5
Posts: 2360
Do it !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you have control of the code on the PC that sends the messages, then you could just implement the flow control i suggested, that would eliminate the need for any buffering beyond the single message to be displayed.

Arduino -> PC "I'm ready, send a mesage"

PC -> Arduino "mesage"

Arduino displays message

and you start over
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem.

If this is not the case then you will have issues, and flow control won't help.
Flow control WILL help, but reducing the frequency of input strings to what can be managed by the Arduino. It will shift the burden of dealing with buffering strings to the sending system, though.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, but if the overall input data speed is > the output data speed all flow control does is, as you say, shift the problem somewhere else. However I don't think that helps unless filling the PC memory and/or disk is considered a reasonable option.

Trouble is we don't know where the data is coming from, how important it is, who's reading the strings and why, are they really going to read every one.

Maybe it's OK to drop strings at the source.

OP?

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, I thought I was getting email notification whenever this thread was updated, but apparently not.  I appreciate all of the responses.

This seems simple enough unless I don't grasp the idea.
As you say have a FIFO of strings and print them one at a time to the LCD.
As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem.
If this is not the case then you will have issues, and flow control won't help.
Rob

Trust me, I'm sure I'm the one who doesn't grasp the idea.  Let me try to simplify the steps for my own sake and see if that helps.

1.) Java app on PC (in this instance the PC is an android) grabs a block of messages from an online source.  Could be anything --  rss feed, twitter, facebook updates, stock market quotes.  Each message could be up to 200 chars in length.  Block may contain as many as 100 messages, but probably will be grabbing far fewer.

2.) Parse block of messages into an array of strings.

3.) Send the individual message strings, one at a time, to the arduino via (in this particular case) bluetooth.

4.) Arduino writes the string to the LCD.

5.) Next message string is sent from PC, and it continues on.

Step 1 & 2 go fine.  Step 3 works to the extent that I'm getting messages on the arduino side.  I start printing messages to the LCD and I run into two limits - the first being individual message length before part of the message is cut off, the second being total number of messages that print (i.e. combined number of characters for multiple messages.)  The first one I can affect by increasing the "#define [sic] ByteBufferLenght" in MeetAndroid.h, but it doesn't eliminate the problem, just allows for longer messages.  The second one I can affect by increasing the "#define RX_BUFFER_SIZE" in Hardware.cpp, but, once again, it doesn't eliminate the problem, just allows for more total characters.

Regarding flow control, I thought I read somewhere that MeetAndroid has some flow control built in in it's send & receive functions/statements by the way it implements the arduino Hardware library.  I could be mistaken, but if it didn't, wouldn't a large array of strings overflow the arduino SRAM regardless what was happening with the LCD?  (Anyone who is laughing right now, remember that I said I'm sure I'm the one who doesn't grasp the idea).

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It's starting to make sense.

Does it matter if a string or strings are dropped?

If not then things get a lot easier.

Quote
part of the message is cut off
Meaning exactly what?

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's certainly preferable if strings don't get dropped.  And I guess I'm wondering why they have to.

Let's say, for instance, the block of 30 messages is grabbed and parsed.  I can conceivably hold onto, update, do whatever endlessly to that array of messages on the pc/android side.  And if the flow control exists already through MeetAndroid (granted, that's an assumption) then the arduino is not getting flooded with message strings, it's just getting one at a time.  So, based on the fact that I was able to affect the message length and combined char limits by increasing buffer settings, it would appear that my roadblock lies within the arduino rx buffer or the lcd's ddram, or both.

It just seems that the arduino should be able to store one complete 200 char message and send it to the LCD at a rate the LCD can handle, then allow it to be overwritten in either or both buffers by the next message, rather than the following messages building up in the buffer along with ones that have already printed (which aren't needed any longer, and if they were, they still exist on the PC/android side) until those buffers are full, which is what appears to be happening.  But it wouldn't be the first time I was wrong.

Cheers,
Tim
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, I've mentioned overall throughput a few times so we'll assume that

a) the overall rate of data in is < that of data out
b) flow control is happening

In this case all you should need is a simple ring buffer and the pseudo code should look something like this

Code:
if (serial.available() != 0) {
    add_char_to_buffer(serial.read());
    if ( buffer_nearly_full()) sendXOFF();
}

if (buffer_is_not_empty()) lcd.print (get_char_from_buffer ());

if (buffer_is_not_full()) sendXON();

______
Rob
« Last Edit: September 08, 2011, 04:49:05 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, Rob.  After doing some exhaustive testing, it appears there isn't flow control happening in the MeetAndroid send/receives that are passing my messages from the Android to the Arduino.  There may be some mechanism for it already built in to the MeetAndroid library and I'm just not appending the proper end-of-message character to trigger it.  I'll have to dig into it further and see if there is such a mechanism or if I need to implement something along the lines of your pseudo-code.

Your assistance is greatly appreciated.

Cheers,
Tim
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Okay, here is my first attempt to implement some flow control, but it's not working.  It stops after about 10 messages.  Any thoughts?

Code:
#include <MeetAndroid.h>
#include <LiquidCrystal.h>

#define LCD_LINES         2
#define LCD_COLUMNS       40

LiquidCrystal lcd(10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9);

/*
  rs:  10
  rw:  13
  en:  11
  db0-db7: 2-9
*/


MeetAndroid meetAndroid;

char msgText[160];
byte msgLength;
byte charCounter;
byte positionMarker;
char space = ' ';

void setup() {
  lcd.begin(LCD_COLUMNS,LCD_LINES);
  Serial.begin(57600);
  meetAndroid.registerFunction(getMsgText, 'z');
}

void loop() {
  meetAndroid.receive();
}

void getMsgText(byte flag, byte numOfValues) {
  boolean lcdIsBusy = true;
 
  while (lcdIsBusy) {
    digitalWrite(13, HIGH);
    delay(300);
    lcdIsBusy = lcdBusy();
  }
 
  msgLength = meetAndroid.stringLength();
  meetAndroid.getString(msgText);
 
  lcd.clear();
  positionMarker = 1;

  // When the message length is less than the number of LCD columns, the message is written
  //   out to the LCD, there is a pause, then the message is scrolled off to the left

  if (msgLength < 42) {
    for (charCounter = 0; charCounter < msgLength - 1; charCounter++) {
      lcd.setCursor(charCounter, 1);
      lcd.write(msgText[charCounter]);
      delay(100);
    }
    delay(2000);
    for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) {
      for (int i = 0; i < LCD_COLUMNS; i++) {
        lcd.setCursor(i, 1);
        if (i + positionMarker >= msgLength - 1) {
          lcd.write(space);
        }
        else {
          lcd.write(msgText[i + positionMarker]);
        }
      }
      ++positionMarker;
      delay(175);
    }   
  }

  // If the message length is longer than the number of LCD columns, the first 40 chars are
  //   written out to the LCD, then at char 41, the message scrolls left until the last char
  //   of the message scrolls off the LCD

  else {
    for (charCounter = 0; charCounter < LCD_COLUMNS; charCounter++) {
      lcd.setCursor(charCounter, 1);
      lcd.write(msgText[charCounter]);
      delay(100);
    }
    for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) {
      for (int i = 0; i < LCD_COLUMNS; i++) {
        lcd.setCursor(i, 1);
        if (i + positionMarker >= msgLength - 1) {
          lcd.write(space);
        }
        else {
          lcd.write(msgText[i + positionMarker]);
        }
      }
      ++positionMarker;
      delay(175);
    }
  }

}


// Checks the LCD Busy Flag

boolean lcdBusy () {
  int busyFlag;
  digitalWrite (10, LOW);  // set RS to low
  digitalWrite (11, HIGH); // set RW to high
  delay(200);
  busyFlag = digitalRead (9); // check db7, which is pin 9
  if (busyFlag == HIGH) {
    return true;
  }
  else {
  digitalWrite (11, LOW);
  digitalWrite (10, HIGH);
  digitalWrite(13, LOW);
  delay(200);
  return false;
  }
}

Thanks,
Tim
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Found this website -- http://www.8051projects.net/lcd-interfacing/busyflag.php  -- and tried to adjust my lcdBusy() function accordingly.  I'm still hitting a message limit, though.  So, either it's not correct and not doing what I think it's doing or it is correct and I have a buffer/flow control problem in another segment of the data path.

It seems if I'm waiting to grab the next message string from the Android (meetAndroid.getString(msgText);) until after I've made sure the LCD isn't busy, the only other place I can see these messages backing up and causing overflow is the buffer in the Arduino that holds the new string from the getString which is then copied into my char string/array variable msgText.  If new messages are accumulating in that buffer rather than overwriting previous, no-longer-needed messages, then the overflow could be happening with the Arduino SRAM.  I've looked for places where I could reset/flush this buffer and the only one that seems directly accessible from my code is a function in the MeetArduino library called meetArduino.flush(), which I've place right after the getString command puts the latest string into msgText -- but it doesn't seem to do anything.

Any idea how to check if that buffer is actually getting cleared?

Latest version of my lcdBusy function:
Code:
boolean lcdBusy () {
  int busyFlag;
  pinMode(9, INPUT);      // set DB7/Pin 9 to input to be able to get busy flag status
  digitalWrite(12, HIGH); // set EN like this because of...
                          //   http://www.8051projects.net/lcd-interfacing/busyflag.php
                          //   I don't really understand the enable pin
  digitalWrite(10, LOW);  // set RS to low (for command register)
  digitalWrite(11, HIGH); // set RW to high (for reading)
  delay(50);
  busyFlag = digitalRead (9); // check status of DB7/Pin 9
  if (busyFlag == HIGH) {
    return true;
  }
  else {
  pinMode(9,OUTPUT);      // reset DB7/Pin 9 back to output
  digitalWrite(11, LOW);  // reset RW back to low (for writing)
  digitalWrite(10, HIGH); // reset RS back to high (for data register)
  digitalWrite(12, LOW);  // toggle EN first to low then to high because of...
  digitalWrite(12, HIGH); // http://www.8051projects.net/lcd-interfacing/busyflag.php
  delay(200);
  return false;
  }
}

Latest version of my complete code:
Code:
#include <MeetAndroid.h>
#include <LiquidCrystal.h>

#define LCD_LINES         2
#define LCD_COLUMNS       40

LiquidCrystal lcd(10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9);

/*
  rs:  10
  rw:  13
  en:  11
  db0-db7: 2-9
*/


MeetAndroid meetAndroid;

char msgText[160];
byte msgLength;
byte charCounter;
byte positionMarker;
char space = ' ';

void setup() {
  lcd.begin(LCD_COLUMNS,LCD_LINES);
  Serial.begin(57600);
  meetAndroid.registerFunction(getMsgText, 'z');
}

void loop() {
  meetAndroid.receive();
}

void getMsgText(byte flag, byte numOfValues) {
  boolean lcdIsBusy = true;
  
  while (lcdIsBusy) {
    digitalWrite(13, HIGH);
    delay(300);
    lcdIsBusy = lcdBusy();
  }
  
  msgLength = meetAndroid.stringLength();
  meetAndroid.getString(msgText);
 meetAndroid.flush();
 
  lcd.clear();
  positionMarker = 1;

  // When the message length is less than the number of LCD columns, the message is written
  //   out to the LCD, there is a pause, then the message is scrolled off to the left

  if (msgLength < 42) {
    for (charCounter = 0; charCounter < msgLength - 1; charCounter++) {
      lcd.setCursor(charCounter, 1);
      lcd.write(msgText[charCounter]);
      delay(100);
    }
    delay(2000);
    for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) {
      for (int i = 0; i < LCD_COLUMNS; i++) {
        lcd.setCursor(i, 1);
        if (i + positionMarker >= msgLength - 1) {
          lcd.write(space);
        }
        else {
          lcd.write(msgText[i + positionMarker]);
        }
      }
      ++positionMarker;
      delay(175);
    }    
  }

  // If the message length is longer than the number of LCD columns, the first 40 chars are
  //   written out to the LCD, then at char 41, the message scrolls left until the last char
  //   of the message scrolls off the LCD

  else {
    for (charCounter = 0; charCounter < LCD_COLUMNS; charCounter++) {
      lcd.setCursor(charCounter, 1);
      lcd.write(msgText[charCounter]);
      delay(100);
    }
    for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) {
      for (int i = 0; i < LCD_COLUMNS; i++) {
        lcd.setCursor(i, 1);
        if (i + positionMarker >= msgLength - 1) {
          lcd.write(space);
        }
        else {
          lcd.write(msgText[i + positionMarker]);
        }
      }
      ++positionMarker;
      delay(175);
    }
  }

}

// Checks the LCD Busy Flag

boolean lcdBusy () {
  int busyFlag;
  pinMode(9, INPUT);      // set DB7/Pin 9 to input to be able to get busy flag status
  digitalWrite(12, HIGH); // set EN like this because of...
                          //   http://www.8051projects.net/lcd-interfacing/busyflag.php
                          //   I don't really understand the enable pin
  digitalWrite(10, LOW);  // set RS to low (for command register)
  digitalWrite(11, HIGH); // set RW to high (for reading)
  delay(50);
  busyFlag = digitalRead (9); // check status of DB7/Pin 9
  if (busyFlag == HIGH) {
    return true;
  }
  else {
  pinMode(9,OUTPUT);      // reset DB7/Pin 9 back to output
  digitalWrite(11, LOW);  // reset RW back to low (for writing)
  digitalWrite(10, HIGH); // reset RS back to high (for data register)
  digitalWrite(12, LOW);  // toggle EN first to low then to high because of...
  digitalWrite(12, HIGH); // http://www.8051projects.net/lcd-interfacing/busyflag.php
  delay(200);
  return false;
  }
}


Thanks,
Tim
« Last Edit: September 09, 2011, 08:43:05 pm by teggroll » Logged

Pages: [1] 2   Go Up
Jump to: