Help a noob send esc commands through Serial port

Using a Uno R3 to communicate with a Noritake VFD display that uses RS232 serial, so I used the SoftwareSerial port with Inverted signal option. So far, so good - display understand basic text.

But I think I'm doing something wrong setting up variable constants to send escape commands for special features on the display... One command sequence needs to send the following hex codes that I defined using char:

char FONT_MAG_X1Y2[] = {0x1F + 0x28 + 0x67 + 0x40 + 0x01 + 0x02};

later in my code, I refence that string via:

mySerial.write(FONT_MAG_X1Y2);

but the display is not processing that command string correctly. I know for a fact that this command string is correct because I have a Noritake demo utility that generates the identical code string and it works using a USB to serial adapter. My Ardunio code must not be sending the same data for some reason. I notice that if I hover over the FONT_MAG_X1Y2 reference in the myserial.write line a popup box shows the string definition buit also says:

variable FONT_MAG_X1Y2
Type: char[1]
Value = {-15}
Passed as str
char FONT_MAG_X1Y2[] = {0x1F + 0x28 + 0x67 + 0x40 + 0x01 + 0x02}

Which leads me to think that perhaps the compiler is interpreting that as some calculation and sending -15 to the display over the serial port.

Any thoughts? Am I defining my strings correctly?

Edit - I've Googled for hours trying to solve this on my own but that just makes me more confused. So many discussions about char vs string etc. And I can't find a good example of concatenating ascii hex codes in C.

TIA

No.


"\x1F\x28\x67\x40\x01\x02"

LOL - I'll bet that's my problem.

I'm a VB guy, sometimes I struggle with C. I'll give this a whirl.

Thanks!

EDIT - Yup, that was the problem. User error, as always lol.

Really appreciate the help!

First of all, please always send here your current and complete sketch code (remember to mark it with "<CODE/>" tag button), so we can better understand your issue.

You defined that "FONT_MAG_X1Y2" variable as a string (we'll discuss later about "C strings" and "String" class) but as it looks like a byte (escape) sequence, i think you better define it as a byte array, like this:

byte FONT_MAG_X1Y2[] = {0x1F, 0x28, 0x67, 0x40, 0x01, 0x02};

So, you can send that sequence to serial using this code:

  for (byte i=0; i<6; ++i) {
    mySerial.write(FONT_MAG_X1Y2[i]);
  }

Further descriptions and suggestions about "C strings" and probably also a general better coding (just to mention, uppercase symbols are conventionally used for constants, so if that "FONT_MAG_X1Y2" is a constant you should define it as "const byte FONT_MAG_X1Y2", and if it's instead a standard variable, you can use the so called "CamelCase" identifiers, e.g. "FontMagX1Y2") will follow as soon as you'll post your full code.

Thanks for the tips! I will endeavor to use the code comments in future.

The earlier suggestion works perfectly - no need to loop through the array...

const char FONT_MAG_X1Y2[] = "\x1F\x28\x67\x40\x01\x02";
...
mySerial.write(FONT_MAG_X1Y2);

As for strings vs constants, yes I intend these to be constants and will add the 'const' declaration - I need to read up on that topic as I know that in some constants (or strings?) gets confusing and requires pointers... I'm not there yet lol.

Sure, I just pointed on the variable/array purpose: if you have printable characters you can use "char" arrays, if you need some "binary" data (even if they're just escape bytes) my advise is to always treat them as a "byte" array. Remember "char" are "signed bytes" (i.e. range from -128 to 127) while "byte" are unsigned (i.e. range from 0 to 255). This is the main reason why I pointed you the difference out... Escape sequences are usually 7 bits, so they are always less than 128, and in this case the difference isn't exactly required, but it's a good practice to always tread characters as "char" and any other byte value as "byte".

Aside from that, do you still need an explanation of the differences between "C string" and "String"?

Yes, if you have the time. I'm aware they exist, but not sure when or how to use each option.

I take your point about the variable/array... I will revise my code to use the byte format as good practice going forward - thanks!

To make things easier in a single sentence, you can assume "C strings" (aka "char arrays") as the default way to store strings, while the "String" is a class where you can manage strings more easily, in a way similar to other high level languages.
I will now try to summarize a little the pros and cons of the two solutions.

Getting a bit into deep, "C strings" are "pointers" to a memory location containing a sequence of characters/bytes, ended with a null (0 value) byte. For example, the string:

char greetings[] = "Hello";

is represented with "greetings" variable containing the address of the first byte where the string "Hello\0" is stored (please note it's 6 bytes in total, the 5 bytes string "Hello" followed by a zero byte). When you access the "C string" (let's call it just "string", with lower case "s") the program reads the variable containing the address, the uses it to cycle the characters, ending when '\0' is reached.
If you have a variable length string, you should define its length as the longest string you will store, plus 1. It means that the definition:

char name[20];

will allocate 20 bytes, to allow storing a string made of up to 19 characters. It sounds a bit "tough" to define, but it allows you to control the memory allocation (and its amount) in a small MCU like Arduino where you don't have tons of Gbytes to work with, like you do with PCs.
With regular "strings" you also need to use functions to manipulate the data, for example to concatenate two strings you must use "strcat" function:

  char str1[20] = "Hello";
  char str2[] = " world";
  strcat(str1, str2);
  Serial.println(str1); // Output is "Hello world".

Now let's dive right in the "String" (with the upper case "S"): it's a "class", a definition higher level languages have, with "object-oriented" framework. It's easier to manage because you can use methods and functions like the ones you see on Java or C#. The drawback is in its memory allocation, and you cn't esily control the storage. Arduino doesn't have a real Operting System, and in this case lacks of a "Garbage collector" function: this means if you create a String variable, use it, and then unload it (for local variables it's automatically made when exiting a function) the memory release creates a "hole". If you perform many operations with "String" variable, it isn't uncommon to see the code malfunctioning, up to a complete lock. So, "Strings" are generally avoided, at least with boards with small memory size (like Arduino UNO)

Here you can read more about this memory problem with "String":

I hope I was clear enough even if it's not easy in a few lines.

Thanks! I get it. While C is new to me, I've been programming code since assembler on my VIC-20. I am aware of the pointer issue and memory management, but not familiar with how the C compiler manages things.

I appreciate the tips and your time!

Cheers!