Difference between printing an array and printing individual characters

Hi,

What's the difference between printing an array of characters in one go and printing the same set of characters one-by-one?

Have a look at this bit of working code....

      char myBuffer[100];
      int z=0;
      // Read entire set of bytes in and copy them into character array
      while(PduEnc.available() > 0)
      {
        byte y = PduEnc.readPduChar();
        myBuffer[z+1]=0;
        myBuffer[z]=(char)y;
        z++;
      }
      // Display character array on screen
      Serial.print("myBuffer<");Serial.print(myBuffer);Serial.println(">");
      // Output full character array to SMS module on port 3
      Serial3.print(myBuffer);

It's part of a project that uses an arduino mega to send SMSs. This snippet reads in a set of characters from my PDU encoder class into a large buffer, (myBuffer) and then outputs the contents of this buffer to the SMS module on serial port 3.

As I said, this code works fine, the SMS get's sent without problems but it requires the use of a temporary staging area myBuffer which takes up a lot of space that I can't afford. (my example uses 100 characters, but it ought to be over 300 for full functionality).

My solution is this snippet, it reads each byte in from the encoder (one by one), and then outputs it straight away to the SMS module on Serial3......

      // Read each PDU encoded byte from the encoder and write it straight to the SMS module 
      while(PduEnc.available() > 0)
      {
        byte y = PduEnc.readPduChar();  // Read in a single byte
        Serial.print((char)y);          // Display single byte to screen
        Serial3.print((char)y);         // Output single byte to SMS module on port 3
      }

This doesn't work, I get an error from the SMS module (The error is "Invalid PDU mode parameter" - which basically seems to mean there's something wrong with your data!). I've experimented with reading and writing the data as both bytes and characters and casting between the two but with no progress, the data is also echoed to the display and appears identical in both cases, my best guesses so far are either that the 'print' command handles arrays of characters differently to individual characters, OR that by printing each character one by one I'm some how screwing up the baud rate that the SMS module expects to receive the data at.

Help please!

        byte y = PduEnc.readPduChar();  // Read in a single byte
        Serial.print((char)y);          // Display single byte to screen
        Serial3.print((char)y);         // Output single byte to SMS module on port 3

This I don't understand. If you are going to cast the value read from the PduEnc instance to a char, why is the variable not a char?

my best guesses so far are either that the 'print' command handles arrays of characters differently to individual characters, OR that by printing each character one by one I'm some how screwing up the baud rate that the SMS module expects to receive the data at.

It's the latter.

Thanks for the response Paul

why is the variable not a char?

The code has gone through several byte/char variations (to see if it made any difference) this just happened to be the version I posted.

It's the latter.

How sure are you that this is the case? Is there any way to know for certain? I only suggested it because I couldn't think of any other possibilities

If it is the case, is there any cure or workaround? If I'm going to need a 300 byte buffer (minimum) then this is really going to make a massive hit on my (already tight) memory requirments.

There is some time involved in reading a character from the serial buffer, and printing it to another serial port. I would guess that the delay between characters is causing problems. If you send "AT" to a phone, for instance, it expect that the whole command will arrive with some time period. If the T arrives late, the A won't be recognized as a valid command.

I have no idea what is being generated by your PduEncoder class, but, surely there is meaning to less than 300 characters at a time.

Perhaps the answer is to fix the lack of memory? Perhaps some optimizations elsewhere may give you the space you need

Thanks for the responses.

If you send "AT" to a phone, for instance, it expect that the whole command will arrive with some time period. If the T arrives late, the A won't be recognized as a valid command.

I understand this, but on the other hand if I send “AT+CMGS=” using a single Serial.print command, and then use a 2nd Serial.print() command to send a second array containing the phone number, then the SMS module is quite happy to accept this as all being part of the same command, despite what is presumably a delay (albeit only fractions of a second) between the two statements.

I have no idea what is being generated by your PduEncoder class, but, surely there is meaning to less than 300 characters at a time

The PduEndcoder class takes a plain text SMS message (160 Characters max) and converts it to PDU format for processing by the SMS module, the PDU encoding translates 1 plain-text character into two pdu-encoded characters.
I started with the PduEncoder library on the arduino home, it works ok, but it uses String types which take up lots of memory and seem to cause fragmentation issues. I re-wrote the library to process the plain-text message one character at a time and provide the pdu-encoded message one character at a time. At the time I thought I’d done a great job, the data memory used by the library went down to less than 75 bytes, however, it now seems my work was pointless because although the new library can generate the pdu-encoded text one character at a time, the SMS module won’t except it one character at a time and only works if it gets the whole pdu-encoded text in one big block. Bu993r!

The SMS module I’m using (SM5100B-D from sparkfun) allows the transmission of plain text messages up to 140 characters long, but if you want to transmit 160 characters messages (which I do
) then they need to be PDU formatted. My project sends a lot of data via SMS so if I switch to 140 characters then I’ll have to send more SMSs (and get bigger bills)

Perhaps the answer is to fix the lack of memory?

Yeah – I know and I’ve been making dramatic improvements (you should have seen how much memory the first versions used!) My project involves sending a lot of data via SMS, but more importantly, it saves the data if it can’t transmit when there’s no phone signal. If I have to add a new 300+ byte buffer then that’s at least two 160 character messages that I can no longer back up!

Thanks for your help, I’ll carry on experimenting. I wonder what happens if I try sending normal AT commands 1 byte at a time? Or maybe I can get away with passing my PDU string in ten 30 byte arrays instead one big 300 byte one.

The PduEndcoder class takes a plain text SMS message (160 Characters max) and converts it to PDU format for processing by the SMS module, the PDU encoding translates 1 plain-text character into two pdu-encoded characters.

OK.

I re-wrote the library to process the plain-text message one character at a time and provide the pdu-encoded message one character at a time.

This is not a logical thing to do, in my mind. Take a plain text message one character at a time, and return TWO pdu-encoded characters would make sense. Worth a try, anyway.

Hi Paul,

Just to clarrify, the process calculates the pdu encoded characters two digits at a time, but returns them one-by-one. It returns data one byte at a time each time it's called until no further bytes are available. Similar to reading from a serial port or similar device.

Cheers

Just to clarrify, the process calculates the pdu encoded characters two digits at a time, but returns them one-by-one. It returns data one byte at a time each time it's called until no further bytes are available.

My thought was that the delay between those two characters is what is causing the issue. Fetch both of them, and send them as a pair. Might help, might not.

Thats actually a very good idea, each individual byte is one of a pair of hex octets - maybe the SMS module is expecting to recive them both at once.

I'll give that a go (tomorrow) and let you know.

Thanks

Can u lower the baud rate on the sms device? Maybe with a lower baud ratr it will be more accepting to small pauses

well, I seem to have a solution, but I'm not sure why. This snippet works....

      // Copy each byte into a string and process one string at a time
      char myBuffer[2];
      myBuffer[1]=0;                    // null terminate the the string
      while(PduEnc.available() > 0)
      {
        byte y = PduEnc.readPduChar();  // Read a single byte
        myBuffer[0]=(char)y;            // Move the byte just read into the sring
        Serial.print(myBuffer);         // Display single byte to screen
        Serial3.print(myBuffer);        // Output single character string to SMS module on port 3
      }

Basically, I copy each character into a 2 byte string (i.e. my data byte, followed by a null terminator) before printing it to the SMS module, it works (which is good!) but I'd like to understand why!
Going back to the title of this thread, I guess the difference between printing an array of characters and printing an individual characters is that an array of characters ends with a null terminator, but individual characters don't (I don't know if this effects how print() handles it). Bearing this in mind I went back to the 2nd bit of code in my original snippet and added the following line after the loop.Serial3.print('0'); to finish off with a null, however this didn't make any difference (it still didn't work).

to finish off with a null, however this didn't make any difference (it still didn't work)

The NULL is not sent. It's a marker that says keep processing elements in this array until you see me.