Go Down

Topic: Serial has no terminator, so use a word for one? (Read 1 time) previous topic - next topic

gazz292

Im trying the safestrings version out now, but i'm getting an error i dont know how to interpret.

i'll post the sketch in the next post, and ask the questions in the post after due to the character limit, partly because i type so much trying to give too much detail, but here it's the length of the code.

I've changed the names of the tokens and commented as much as i can to it makes sense to me (well part of it does)

one thing i've noticed is i've broken the 'test data' bit, when i uncomment that and open serial monitor it just goes 'Automate 3 2 1' the numbers counting don (i changed them from 10 to 3 for faster startup)
So i'm wondering what i did to break that part.

gazz292

Code: [Select]
// install the SafeString library from Arduino library manager
//  see the tutorial at www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
// also see Text I/O for the Real World https://www.forward.com.au/pfod/ArduinoProgramming/Serial_IO/index.html#SafeStringStream
/* 
 *   Text to use with serial monitor to test 'This sketch only':
 *      1,76,1,0,14:36,-; 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt,
 */

#include <SafeString.h>
#include <BufferedOutput.h>
#include <SafeStringStream.h>
#include <LiquidCrystal.h>
#include <NoiascaLiquidCrystal.h>      // Umlaut lcd lib.
#include <NoiascaHW/lcd_4bit.h>        // Use the parallel interface, 4bit mode. Alternatives are I2C and SPI.

// Set up the LCD:
const byte cols = 24;                 // Columns/characters per row
const byte rows = 2;                  // Rows
const byte rs = 8;                    // Register Select pin
const byte en = 9;                    // Enable pin
const byte d4 = 7;                    // Data bus pin D4
const byte d5 = 6;                    // Data bus pin D5
const byte d6 = 5;                    // Data bus pin D6
const byte d7 = 4;                    // Data bus pin D7
const byte bl = 10;                   // Back light, Set to 255 if not used
LiquidCrystal_4bit lcd(rs, en, d4, d5, d6, d7, bl, cols, rows, convert_special);   

#define TEST_DATA
#ifdef TEST_DATA
const uint32_t TESTING_BAUD_RATE = 9600; // how fast to release the data from sfStream to be read by this sketch
cSF(sfTestData, 340); // the test data SafeString, will be filled in setup()
cSF(rxBuf, 64); // the extra rxbuffer for the SafeStringStream to mimic the Uno hardware serial rx buffer
SafeStringStream sfStream(sfTestData, rxBuf); // set the SafeString to be read from and the SafeString providing the rx buffer

Stream& inputStream = sfStream; // set input to test data;
#else
Stream& inputStream = Serial; // set input to test data;
#endif

cSF(sfReceived, 150); // Receive buffer
createBufferedOutput(bufferedOut, 150, DROP_UNTIL_EMPTY); // create an extra output buffer so debug msgs dont cause missed input

cSF(Time, 10);  // Current time in simulation
cSF(IbisLine1, 30);  // Top line of IBIS text, '30' = number of bytes allowed for in buffer
cSF(IbisLine2, 30);  // Bottom line of IBIS text
cSF(Delay1, 10); // Running delay + or - symbol if present
cSF(Delay2, 10);  // Running delay numbers


void setup() {
  Serial.begin(115200); // start serial coms at the speed indicated
  for (int i = 3; i > 0; i--) {
    Serial.print(' '); Serial.print(i); // Count down from 3 to allow time to open serial monitor
    delay(500);
  }
  Serial.println(); 
  lcd.begin();                         // Initialize the LCD
  lcd.backlight();                     // Turn on backlight
  lcd.createUml();                     // Create 3 German Umlauts using Special Characters 5, 6, and 7 - used for convert_special
   
  SafeString::setOutput(Serial); // enable error msgs??
  bufferedOut.connect(Serial);
#ifdef TEST_DATA
  Serial.print("Automated Serial testing at "); Serial.println(TESTING_BAUD_RATE);
  sfTestData = F(
                 "1,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt," // missing field
                 //                 "1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt,"
                 "1,0,0,0,12:45,.,,0,0,-1,,noch nicht mit leben gefüllt,"
                 "1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt," // good data
                 "1,0,0,0,12:45,.,,0,0,-1,,noch nicht mit leben gefüllt,"
               ); // initialized the test data
  Serial.println("Test Data:-");
  Serial.println(sfTestData);
  Serial.println();
  sfStream.begin(sfTestData, TESTING_BAUD_RATE); // start releasing sfTestData at 9600 baud call this last
#endif
  // else read from Serial
}

bool processInput(SafeString &input) {  // do error checking here on input
  size_t idx = 0;  // count the number of fields
  size_t fieldCount = 0;  // Start at  zero
  while (idx < input.length()) {
    idx = input.indexOf(',', idx);  // Search for commas
    if (idx < input.length()) { // found one
      fieldCount++;
      idx++; // Move past last comma and look for next one
    }
  }
    if (fieldCount != 12) {
    bufferedOut.print(F("Bad data field count:")); bufferedOut.println(fieldCount);
    return false;
  }
  cSF(sfField, 12); // for the fields  does not matter is its too small idx is still updated and empty SafeString returned
  bool returnEmptyFields = true;  // Prevents skipping of unpopulated fields (as happens with Strings when electric is off, or IBIS reset)
  idx = 0;  // Start at zero
  for (int i = 1; i < 5; i++)  {  // Count fields, skip the first 4
    idx = input.stoken(sfField, idx, ',', returnEmptyFields); // Split the fields up at the commas
  }
 
  // Read text in Time field
  cSF(Clock, 10);  // Allow 10 bytes worth of buffer space
  idx = input.stoken(Time, idx, ',', returnEmptyFields); 
  // Read text in Running delay field
  cSF(Delay, 10); // Allow 10 bytes
  idx = input.stoken(Delay, idx, ',', returnEmptyFields); 
  // Read text in IBIS lcd field
  cSF(Ibis, 100); // Allow 100 bytes
  idx = input.stoken(Ibis, idx, ',', returnEmptyFields);
 // if (Ibis.isEmpty()) {
 //   bufferedOut.println(F("Power Off")); // Not using as empty field can also be Ibis not yet set up / reset
 //  return false;
//  } 

  // do field error checking here
  // do not update globals if there are errors
  // if all OK update data
  idx = 0;
  // stoken always clears the return first
   idx = Delay.stoken(Delay1, idx, ';'); // Need to change this to split at first character, which can be a '+' a '-' or a space.. which indicates you are on time...
  idx = Delay.stoken(Delay2, idx, ';'); //... if running on time,numbers will be 0.0 and no + or - symbol above. if just a dot (,.,) = ibis not set, reset, bus power is off or timetable not yet selected.
  idx = Ibis.stoken(IbisLine1, idx, '@');  // Split first part of IBIS lcd at the @ symbol, and put it in 'IbisLine1'
  idx = Ibis.stoken(IbisLine2, idx, '@');  // Split second part of IBIS lcd contents, to 'IbisLine2'
 
//  Time.clear();  // Clear the Time so it can be updated
//  Time = Clock;  // Rename Time - Clock ... these stop Time from printing
  return true;
}
bool getAndProcessInput() { // collect the text strings and do something with them
  bool rtn = false;
  if (sfReceived.read(inputStream)) { // read from input
    if (sfReceived.endsWith("gefüllt,")) {  // Search for that word in the string, which is used to terminate the string
      rtn = processInput(sfReceived); //  Now write the text to the lcd and or serial monitor
      sfReceived.clear(); // Free up for next line
      return rtn;
    }
  }
  if (sfReceived.isFull()) {  // If receive buffer full, keep the last few chars so we will find "gefüllt,"
    bufferedOut.println("sfReceived overflowed, too small or bad data");
    sfReceived.keepLast(10);
  }
  return false; // No new input or have errors
}

void LCDprint() {
  // Start printing text to the LCD
     lcd.setCursor(0, 0); // Sets cursor on the LCD, column, row.
     lcd.print(IbisLine1); // Displays the first line of text
     lcd.setCursor(0, 1);
     lcd.print(IbisLine2); // Displays last line of text
     lcd.setCursor(21, 0); // move cursor here, print the delay  -, or + symbol above the numbers as on the real IBIS.
     lcd.print(Delay1); // Running delay... still need to split this field
     lcd.setCursor(20, 1);
     lcd.print(Delay2);
}
void loop() {
  bufferedOut.nextByteOut(); // Push buffered output to Serial <<<<<<< important

  if (getAndProcessInput()) {  // If new data available
    bufferedOut.print("Ibis Line 1: "); bufferedOut.println(IbisLine1);
    bufferedOut.print("Ibis Line 2: "); bufferedOut.println(IbisLine2);  // Print the texts to the serial monitor
    bufferedOut.print("Delay Line 1: "); bufferedOut.println(Delay1);
    bufferedOut.print("Delay Line 2: "); bufferedOut.println(Delay2);
    bufferedOut.print("The Time is: "); bufferedOut.println(Time);
    bufferedOut.println("---------------------------------");
    LCDprint(); // Send the above to the lcd.
  }
}



gazz292

What i'm trying to do is split the 'Delay' up like the 'Ibis' one is, only i don't have a character i can use like the Ibis does (which uses @)
i want to split the Delay after the first character, so i can put the + or - symbol on the top LCD line, and the numbers that are after it on the lower line... the ';' is what i manually put in the text i paste to the serial monitor just to get it to work, so i need to replace ';' with the safestring version of 'charAt'??


But when i try to use the sketch with serial monitor, i'm getting a safestring error of :
Code: [Select]
Error: Delay.stoken() fromIndex 41 >  Delay.length() : 6
        Delay cap:100 len:6 '-; 4.2'
Error: Delay.stoken() fromIndex 7 >  Delay.length() : 6
        Delay cap:100 len:6 '-; 4.2'


I think its the 'fromIndex 41' bit? that number is too high if it's what i think it is... i.e. the number of characters into the token it is reading from?
i've played around with larger and smaller buffers and things like that, no change other than the expected when i go to small.


If i move the position of the code that calls the 'Delay' data from below the 'Ibis' part to a over it, like so:
Code: [Select]
  idx = Delay.stoken(Delay1, idx, ';');
   idx = Delay.stoken(Delay2, idx, ';');
   idx = Ibis.stoken(IbisLine1, idx, '@');
   idx = Ibis.stoken(IbisLine2, idx, '@');



Then i dont get the error, but instead i lose the beginning of the IbisLine1 text... like so:
Code: [Select]
Ibis Line 1: f Krkhaus    
Ibis Line 2: 076   01 105    6 A
Delay Line 1: -
Delay Line 2:  4.2
The Time is: 14:36


Note the 'E-dor' is missing from Ibis Line 1:
How many letters i lose depends on how many characters are in the Delay part of the input string.. i.e. don't the ';' character and i get a character back in the Ibis Line 1.

drmpf

First the error
Code: [Select]
Error: Delay.stoken() fromIndex 41 >  Delay.length() : 6
        Delay cap:100 len:6 '-; 4.2'

Yes the idx arg exceeds the length of the Delay SafeString, most likely you are using a value of idx left over from a previous stoken call,  Start from 0 again  i.e. idx = 0;

If, in future, you need more help tracking down where the error is, you can add 
Delay.debug("point1");  
statements to print out the current value and size of Delay at various points with a label "point1" 

This section code has the same problem, you need to start from 0 again when tokenizing another string
Code: [Select]
 // stoken always clears the return first
   idx = Delay.stoken(Delay1, idx, ';'); // Need to change this to split at first character, which can be a '+' a '-' or a space.. which indicates you are on time...
  idx = Delay.stoken(Delay2, idx, ';'); //... if running on time,numbers will be 0.0 and no + or - symbol above. if just a dot (,.,) = ibis not set, reset, bus power is off or timetable not yet selected.
  idx = 0; // add this to start again for an new SafeString   <<<<<<<<<<<<<<<<<<<<<<<<<<
  idx = Ibis.stoken(IbisLine1, idx, '@');  // Split first part of IBIS lcd at the @ symbol, and put it in 'IbisLine1'
  idx = Ibis.stoken(IbisLine2, idx, '@');  // Split second part of IBIS lcd contents, to 'IbisLine2'
 

But assuming there is always a + or - at the front of the delay you can just use 

Code: [Select]
Delay1 = Delay[0]; // or Delay.charAt(0);

and then just select the rest

Code: [Select]
Delay.substring(Delay2,1);
   
The revised code is attached.  Note I have reduced the size of the sfTestData to suit just one test line

drmpf

The test output is
Code: [Select]
09:19:43.500 -> Automated Serial testing at 9600
09:19:43.500 -> Test Data:-
09:19:43.500 -> 1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt,
09:19:43.500 ->
09:19:43.972 -> Ibis Line 1: E.-dorf Krkhaus     
09:19:43.972 -> Ibis Line 2: 076   01 105    6 A
09:19:43.972 -> Delay Line 1: -
09:19:43.972 -> Delay Line 2:  4.2
09:19:43.972 -> The Time is: 14:36
09:19:43.972 -> ---------------------------------



gazz292

First the error
Code: [Select]
Error: Delay.stoken() fromIndex 41 >  Delay.length() : 6
        Delay cap:100 len:6 '-; 4.2'

Yes the idx arg exceeds the length of the Delay SafeString, most likely you are using a value of idx left over from a previous stoken call,  Start from 0 again  i.e. idx = 0;
Ahhh, that makes sense now,  
Yes i had just tried adding extra 'stoken' calls one after the other, now i understand what the code is doing a little better, Thankyou.

But assuming there is always a + or - at the front of the delay you can just use

Code: [Select]
Delay1 = Delay[0]; // or Delay.charAt(0);

and then just select the rest

Code: [Select]
Delay.substring(Delay2,1);
I think the delay bit might need some extra processing, 
There can be a +, a -, or a blank space (for the few seconds that you are running on time, thankfully the text in that field will be padded correctly... i.e.   
',- 1.2,'   or  ',+24.6,'   or  ',  0.0,'  so always 5 characters when there is a 'delay' to show. thats if blank spaces are picked up as characters 
When there's no timetable selected, the ibis has been reset, power is off, or the 'do not show delay' box is ticked in Komsi (the program that extracts the data from the sim and sends it as a string over serial) then the delay text is not present.
BUT the dot is always there, so for no delay time to be shown that field will show ',.,'  so not an empty field, as the dot is placed there by the program that extracts the raw data from the bus sim.
So that will complicate things a little i think, maybe some 'if / else' statements?  along the lines of 
if 'Delay' contains 1 character only, clear the Delay text on the LCD, 
else show the 'Delay' text and update it as the data changes (with the spaces padding it i dont think i need to call a lcd clear for this, the spaces will overwrite it when going from say ',-10.0,' to ',- 9.9' 

gazz292

dang it, another issue,

I'm using an arduino mega now, with a usb serial dongle connected to serial1 on the arduino, and i changed the sketch to suit this, so what ever i send to the adruino over serial0, the 'serial print' text comes back from serial1.

the issue:
i've just noticed that the string that comes over the serial port doesn't have a comma at the end, i thought it did.
so an actual output is

1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt

Repeated every 200 milliseconds (with fields updating as they change in the sim)


Easy enough to change the word the sketch looks for the word terminate the string from 'gefüllt,' to 'gefüllt'
and i have to also change the field count part to 11.

But i think there's an issue where the first field is then messed up on the next read of the input string, it adds the last text to the first field as that's where the next comma is.

Should i look at putting a comma after the 'gefüllt' word with the sketch, using something like a 'string replace'
tho i'd have thought the sketch see's the word 'gefüllt' then adds a null terminator to it?

I can replicate what's happening when i try live data from the sim simply by putting 2 or more copies of the test string into serial monitor one after the other,
i.e. '1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus     @076   01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt'

This gives me the error i get when the strings are sent 200milliseconds apart from the sim,

Code: [Select]
sfReceived overflowed, too small or bad data
SafeString sfReceived cap:120 len:65 ' 01 105    6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt'
Error: sfReceived.stoken() token SafeString  sfField needs capacity of 15 for token ' 01 105    6 A '
        sfField cap:12 len:0 ''
Error: sfReceived.stoken() token SafeString  Time needs capacity of 11 for token 'Krankenhaus'
        Time cap:10 len:0 ''
Error: sfReceived.stoken() token SafeString  Delay needs capacity of 29 for token 'noch nicht mit leben gefüllt'
        Delay cap:10 len:0 ''
Power Off


Could this be an index not resetting again like last time? or something else.

drmpf

OK looks like the errors you are getting are because the field count is mucked up.
This change worked for me
Code: [Select]
  if (sfReceived.read(inputStream)) { // read from input
    if (sfReceived.endsWith("gefüllt")) {  // Search for that word in the string, which is used to terminate the string
      sfReceived += ','; // add the missing terminator
      rtn = processInput(sfReceived); //  Now write the text to the lcd and or serial monitor
      sfReceived.clear(); // Free up for next line
      return rtn;
    }
  }

drmpf

Actually there may be another issue.
sfReceived.read( ) reads as many chars as are available.
If some other part of your code delays the call to read( ) then the next call to read( ) may read the chars
gefüllt1
if the '1' is available in the Rx buffer as well as the '
gefüllt'  
Then the test for endsWith will fail.

This code will avoid that problem (and also includes the suggested loopTimer which comes with the SafeString library)
Code: [Select]
#include <loopTimer.h>
...
bool getAndProcessInput() { // collect the text strings and do something with them
  loopTimer.check(bufferedOut);
  bool rtn = false;
  while (inputStream.available()) {
    char c = inputStream.read(); // read just one char at a time
    sfReceived += c;  // add it to the chars received so far
    if (sfReceived.endsWith("gefüllt")) {  // Search for that word in the string, which is used to terminate the string
      sfReceived += ','; // add the missing terminator
      rtn = processInput(sfReceived); //  Now write the text to the lcd and or serial monitor
      sfReceived.clear(); // Free up for next line
      return rtn;
    }
  }
  if (sfReceived.isFull()) {  // If receive buffer full, keep the last few chars so we will find "gefüllt"
    bufferedOut.println("sfReceived overflowed, too small or bad data");
    sfReceived.keepLast(10);
  }
  return false; // No new input or have errors
}


However you need to call the getAndProcessInput() method often enough to make sure you don't miss any input.  Might be a bit hard to do at 115200 baud in.  
You may need to
a) call getAndProcessInput() from a number of places in your code or
b) add a BufferedInput to increase the 64char Rx buffer to say 120.

See the Text I/O for the Real World tutorial for the BufferedInput which has stats to help you set the buffer size and Multi-tasking in Arduino for an example of adding extra calls.

To start with add a loopTimer to getAndProcessInput() to check what the delays are between calls. Again see Multi-tasking in Arduino

gazz292

Thankyou, i'll try those suggestions, 

 all this because there's no bloomin terminator on the data stream i want to use, if i knew what i was doing i'd disassemble the code for the program that reads the data from the bus sim and add a terminator.. they are present on the other streams, just this one it was forgotten for.


I wonder if there's a way to sync the string reading to when the arduino receives it's input, as they are sent every 200 milliseconds, 
in plain english.... 'when rx input starts, read incoming string to end then stop, terminate and process the string, wait for the next time the rx input happens, repeat'

I kinda imagine this is what happens with the 'receive with delay' method Sterretje did with Robin2's code (and that you gave me a safestring version)
i'm trying to figure out where to put those bits of code in this one to try that out too.

Robin2

all this because there's no bloomin terminator on the data stream i want to use,
I'm confused. Back in Reply #8 you said
Quote
That receive with time out works, thankyou so much for this.
...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gazz292

i did.... i even wrote a very bloated script based on that to pull the strings out i wanted, 
but i needed to add debugging to the script for when i evolved it and all that, but i was stuck using an uno at the time (i've now found my mega's and bought a CH340 USB to TTL adaptor)

Then i went down the safestrings route... because that looked easier to me having no programming skills. 

i guess it's because i cheated and was given a working bit of code for safestrings tho.

But that's happened before, a working 'example' is so easy to just copy and use.... but i don't get to learn what is going on with it,  
i can cludge about and change a few things in it, but when i break the code i don't understand what's going on to fix it. 

This project of mine will evolve a little, and i may even change where in the string the data is put in the string (thats the only thing i can change in the program that reads the data out of the simulator and sends it as a string on the serial port)  
But the basics of it is to read a serial input that is a string with no terminators,  break the strings up, break some of those strings up again, and display those parts of the strings on an lcd. 

Then i want to add things like blanking the lcd if the simulated bus electric is off, alter the backlight level if the simulated bus headlights are on or off, ensure the text is cleared if needed on the LCD etc.

But i was getting stuck with empty strings causing the array reader to skip over them and read the wrong text,  and the safestrings 'returnEmptyFields' thing fixed that. 


But i am wondering to my self, do i learn the safestrings method, or learn the 'proper' c-strings method with memory management / awareness, 
I know the author of safestrings wants the library to become part of the arduino as standard, but it's a manual add on atm, 
And as I wish to share my completed sketch with the bus sim builder community, and i am thinking that some people don't want to have to download a load of extra libraries just to program one arduino, especially as i'll have to try and explain in German what to do as that's where most of the people who would use this live (as it's a German bus simulator)

Robin2

#42
Jan 14, 2021, 07:31 pm Last Edit: Jan 14, 2021, 07:34 pm by Robin2
But i am wondering to my self, do i learn the safestrings method, or learn the 'proper' c-strings method with memory management / awareness,
I have no reason to be critical of the SafeString library but the dilemma you face is (in my experience) a common one - does learning an allegedly easier library actually take as much or more time than learning the "raw" C++ way of doing it. A huge amount depends on how well a library is documented and knowing the C++ code will probably give you more long term capability (if that matters).

It may be worth spending a little time adapting the example in Reply #5 to use a SafeString just for the purpose of detecting the end-mark word. In other words, using SafeString to the absolute minimum until you become more familiar with it.

I'm not a user of SafeString. Because I don't have any Arduino programs that process text I have never found the C++ functions particularly onerous. The strstr() function will find one string in another.

Whichever route you take. as with any new piece of programming, start with some short programs just for learning. Only introduce the new stuff into your main program when you are confident of the technique.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

gazz292

I think i should learn the C++ way, as i'd like to do other sketches in the future for the other outputs from this bus sim, as well as possibly do inputs for the ticket printer using the arduino due board i have, and that will need a lot of arrays and stuff like that i believe, as well as reading strings and splitting them up again.

I can see how the safestrings way is trying to do what the arduino String stuff should have done, but i do want to learn for the future here,
Like when i get to the force feedback steering system i will make from scratch (mechanically) it uses an STM32 board, i know that can be programmed in the arduino IDE,  but i'm not sure that would accept the safestring method for reading the incoming serial data that translates to the movements of the motor.


So....
i've spent most of the day playing with that sketch i wrote in answer #28, 
Added a simple bit to print the serial output data via Serial1, and played with the program that sends the text strings out, and made it so i have a string for 'bus electricity on or off' and 'lights on or off'  which will help with the bits i add to the sketch later.

Then i added in the Noiasca LCD library and a simple output to the LCD of one string (or is it an array once it's been broken up) 

And apart from when there's empty strings, so far that receive with timeout is working fine, and i do think i understand what is happening in the sketch, 

I now need to streamline it using maths functions to tell it to count the strings and split them off rather than having 2 lines of text for every one, then figure out how to not skip empty strings etc.

drmpf

Don't let me distract you from learning C/C++ char manipulations as they are the basis for all the libraries/code that work with text (including SafeString)

Quote
but i'm not sure that would accept the safestring method for reading the incoming serial data that translates to the movements of the motor
Let me know when you get that far.  I am interested in clarifying where SafeString is applicable and where it is not.

Quote
i am thinking that some people don't want to have to download a load of extra libraries just to program one arduino
It is hard to anything much in the real world with Arduino without downloading a library or two as you have already found out trying to drive the LCD


Quote
i'll have to try and explain in German
I find Google Translate does quite a good job.

Go Up