Need help with data types

Hello, I'm new to Arduino. I have done a little C in the past but I'm rusty. I understand the meaning of the data types but when I try to put them to use I struggle to get the results I expect. For example. I would like to read in a byte from the serial port and based on the value generate a string. I am expecting values from 1 to 200 and I want to convert as follows: if( mybyte == 1) mystring = "song1.mp3"; if( mybyte == 2) mystring = "song2.mp3; and so on.

First off does it even make sense to say mybyte == 1? Is that even correct? Should it be mybyte == B00000001?

Second what type is mystring? Should I use an array of char? Or a string object?

Third I'm confused about how to write results to the serial monitor to debug my code. The code could be correct but serial monitor could be interpreting what I send it in a way I don't expect. I think I read somewhere the monitor gives different results depending on weather you said Serial.print() vs Serial.write()

I understand word vs byte and signed vs unsigned and two's complement and all that jazz. I guess I'm just struggling with syntax and how the compiler interprets things.

-Steve

hello,

mybyte == 1 makes sense, assuming you receive a 1 and not the ascii code of 1 which would be '1'. Second mystring = "xyz" works when mystring is of type char* and declared as char * mystring;

If your string are static and you are not playing around with them, you don't need the string object. If you still want to use them, you have to initialize them with the copy constructor.

If you go he char* way you can print these string with Serial.print(mystring). Serial.write indead is different. For strings it doesn't make a big difference but for numbers. Serial.write(65) sends 'A' (binary 65) while Serial.print(65) prints 65 (number converted to string)

sbennett1298: First off does it even make sense to say mybyte == 1? Is that even correct? Should it be mybyte == B00000001?

Makes perfect sense. The two are identical, as the number "1" is represented as binary pattern 00000001. You can also specify it as '\01' or 0x1.

Second what type is mystring?

Only you know. There is no "type" of a variable unless YOU have declared it. The compiler will throw something about mystring being undefined. If your code said String mystringit is a String data type. (one that looks temptingly easy to use at first, but it has some hidden costs, so it is not recomended) If your code is char mystring[20]it is a character array of 20 letters, where mystring[0] is the first and mystring[19] is the last. Most character handling requires the last character is a zero (0, or '\0' or 0x0 ...) so to store "hi" it would contain mystring[0]='h' mystring[1]='i' mystring[2]='\0' and the content of [3] through [19] is irrelevant (but there if you want a longer string) If your code is int mystringit is a number, and so on.

mystring = "song1.mp3";

If you have declared mystring correct, this is pointer manipulation, but you do not want to go there, yet. If you want to make mystring contain the filename then use strcpy() (not documented in the arduino reference, but it is a standard c routine - google)

The difference between Serial.print(65) and Serial.write(65) is the former will output the letters "6" and "5" which to your eyes looks like the number 65 (but it isnt 65 dots is it?), and the latter will ouptut the binary value 65 which the serial monitor shows as a single character - which happens to be the letter A. That is because the Serial monitor can not show binary, only characters. The computer is ALL BINARY - the concept of characters and numbers is our INTERPRETATION of what the binary value represents. That is why 'A', 65 and 0x41 and B01000001 all are the same.

No my strings are not static. Not unless I want to list 200 of them. The example I gave was simplified for the sake of discussion. What I really want to do is take a byte between 1 and 200 and map it to a string like: (this is a juke box app) 1 becomes "A1.mp3" 2 becomes "A2.mp3" ... ... ... 198 becomes "V8.mp3" 199 becomes "V9.mp3" 200 becomes "V0.mp3"

Every possible combination of 20 letters and 10 digits. To complicate matters there is no "I" and no "O". I guess the juke box maker omitted these letters to avoid confusion with one and zero. Yes the strings could be static if I wanted to explicitly list 200 combinations in my code but I would rather write a routine to map the byte to the string it represents. My grasp of C is lacking. lol

-Steve

Thanks this is helping. I have used pointers before but it was a long time ago and I'm rusty. Pointers and references and such are way back there in the cob webs of my brain. lol

Using a large if statement is overkill. This can be done with a simple division, modulus division, and sprintf():

int someNumber = 185;
char songName[7]; // buffer to store name
char letter = someNumber / 10 + 'A'; // 185 / 10 + 'A' = 'S'
int numb = someNumber % 10 + '0'; // 185 % 10 + '0' = '5'
sprintf(songName, "%c%c.mp3", letter, numb); // songName will contain "S5.mp3"

Uncompiled and untested, but it should give you the idea on how to do it.

sbennett1298: What I really want to do is take a byte between 1 and 200 and map it to a string like:

That could be done by declaring an array of strings, and using the byte value as the index into the array. If you have a lot of strings, it would be sensible to store them in progmem rather than in RAM.

sbennett1298: No my strings are not static. Not unless I want to list 200 of them.

I'm not sure what that means. Does it mean the string values aren't hard-coded in the sketch? If so, how do they get defined and where are the definitions stored?

Edited to add: Oh, I think you mean the relationship follows a known formula and you'd prefer to work the string out from the number rather than hard-code the mappings. That's easy enough to do, but would just require a small amount of fiddling to deal with the unused characters.

That could be done by declaring an array of strings, and using the byte value as the index into the array. If you have a lot of strings, it would be sensible to store them in progmem rather than in RAM.

Yes exactly! I had the same idea but when I looked at the reference the closest thing i saw to an array of strangs was an array of chars.

Oh, I think you mean the relationship follows a known formula and you'd prefer to work the string out from the number rather than hard-code the mappings. That's easy enough to do, but would just require a small amount of fiddling to deal with the unused characters.

Yes exactly. The combination of both things you said. Build an array of strings with the byte as the index and do it in code that does the math. I just don't know how to make an array of strings and I have trouble with the data types.

int someNumber = 185;
char songName[7]; // buffer to store name
char letter = someNumber / 10 + 'A'; // 185 / 10 + 'A' = 'S'
int numb = someNumber % 10 + '0'; // 185 % 10 + '0' = '5'
sprintf(songName, "%c%c.mp3", letter, numb); // songName will contain "S5.mp3"

Yes thanks for steering me in the right direction. This is exactly the sort of think I want to do.

An array of strings is really pretty simple.

PROGMEM char *SongNames[] = {"A1.mp3", "A2.mp3", "A3.mp3", "A4.mp3", "A5.mp3", "A6.mp3",
...
"V8.mp3", "V9.mp3", "V0.mp3"};

char mystring[7];  // Or bigger.  Max stringsize + 1
byte mybyte;

...

  strcpy_P(mystring, songNames[mybyte]);
  Serial.println(mystring);

Arrch,

Your code compiled and worked great. I learned a lot from it. I only had to make minor changes to get the bytes to map to the song names for my particular case. Thanks to everyone who replied. I learned a lot from all of you. Here is my code based on what you sent me.

/* 
     1    2    3    4    5    6    7    8    9    0
  --------------------------------------------------
a    1    2    3    4    5    5    7    8    9   10
b   11   12   13   14   15   16   17   18   19   20
c   21   22   23   24   25   26   27   28   29   30
d   31   32   33   34   35   36   37   38   39   40
e   41   42   43   44   45   46   47   48   49   50
f   51   52   53   54   55   56   57   58   59   60
g   61   62   63   64   65   66   67   68   69   70
h   71   72   73   74   75   76   77   78   79   80  ### I gets skipped
j   81   82   83   84   85   86   87   88   89   90
k   91   92   93   94   95   96   97   98   99  100
l  101  102  103  104  105  105  107  108  109  110
m  111  112  113  114  115  116  117  118  119  120
n  121  122  123  124  125  126  127  128  129  130  ### O gets skipped
p  131  132  133  134  135  136  137  138  139  140
q  141  142  143  144  145  146  147  148  149  150
r  151  152  153  154  155  156  157  158  159  160
s  161  162  163  164  165  166  167  168  169  170
t  171  172  173  174  175  176  177  178  179  180
u  181  182  183  184  185  186  187  188  189  190
v  191  192  193  194  195  196  197  198  199  200

*/ 
char songName[7]; // buffer to store name
int someNumber = 200;
void setup(){
  Serial.begin(9600);
  
  
}

void loop(){

  char letter = (someNumber - 1) / 10 + 'A'; // 185 / 10 + 'A' = 'S'
  if(someNumber > 80) letter++; // the alphabet skips I so adjust for that.
  if(someNumber > 130) letter++; // the alphabet skips O so adjust for that too.
  int numb = someNumber % 10 + '0'; // 185 % 10 + '0' = '5'
  sprintf(songName, "%c%c.mp3", letter, numb); // songName will contain "S5.mp3"
  Serial.println(songName);
  while(1){}
}