Random Alphanumeric Generator

Hello All, I am looking to create/obtain a random alphanumeric generator for arduino. I searched the forums and online for a solution that works in the arduino environment but came up short, so I decided to write my own. Below is my code. If you know of another random alphanumeric generator that works in the arduino space can you please just provide it? It is hard to explain exactly how my code acts. It is interesting to see how it works, as it is anti intuitive of what I'd/you'd expect. The size of the random string will be between 0 and 16000 as I will be sending over packets up to 16M and want to test it first with random bit to check for bit errors. I believe the reason I seeing what I am seeing is because of the max memory on the arduino. Please take a look and let me know what you think. Thank you.

int numBytes = 0;
int i = 0;
int j = 0;
String letters[40] = {"a", "b", "c", "d", "e", "f","g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
String randString = "";

void setup() {
  Serial.begin(230400);
}

void loop() {
  if(Serial.available()) 
  {
    numBytes = Serial.parseInt();
    for(i = 0; i<numBytes; i++)
    {
     randString = randString + letters[random(0, 40)];
     Serial.println(randString);
    }
    Serial.println("Here is your random string: ");
    Serial.println(randString);
    Serial.print("I received: ");
    Serial.println(numBytes);
    delay(1000);
  }
}
String letters[40]

Dumb. That's a huge amount of waste to hold 40 characters.

char *letters = "abcdefghijklmnopqrstuvwxyz0123456789";

Even that is pointless.

   byte randomValue = random(0, 37);
   char letter = randomValue + 'a';
   if(randomValue > 26)
      letter = (randomValue - 26) + '0';

The value in letter will be the same as what was in letters[randomValue].

Thank you for your reply. I am new to programming, and I am still having difficulty. If I understand your code correctly you are supplying me with a random character. How do I then append that character to the end of a string? Below is my code with a minor change and the output I input varying numbers, the first three inputs were intentionally 600.

void loop() {
  if(Serial.available()) 
  {
    numBytes = Serial.parseInt();
    if(numBytes > 0)
    {
      for(i = 0; i<numBytes; i++)
      {
       randString = randString + letters[random(0, 36)];
      }

    Serial.println("Here is your random string: ");
    Serial.println(randString);
    Serial.print("I received: ");
    Serial.println(numBytes);
    delay(1000);
    }
  }
Here is your random string: 
re91ymcjqcp847c5ftospj40eknf278vj3smki6duw25hcywtj4crus9vjj6xgzthddfp2j2abchsc7yj68q5pq67qvcxukw76i9bkr0stt9y6ohvo5lgziam1mpyi1pixdvrmw1fv747de4e5y2nh5gorjfuox70vo702lp1r48uopw4rihxwbbnr9ieug3myq0yto827x6edf8meojxkhlwnhh00kio6afznhyy380wefvnapb4dmif3xjuwmwpu3d5cp7kw9n081wjgqrslykeidd7jhamqnpzsdu12rh
I received: 600
Here is your random string: 
9xkr6b40qw2huqkcdjbg1tqxeb2kvvag7dsqskyxj07atnvcbi5l3ai3xj30k32qoyeai1uj8th6gxfsysaj93pa4089alz2spx1n9kguim8ha1f4sjg9mr3gj57hcxz8qcmdbt3r7mk3yh52m0xartf98ij38vjpdhkkygrh13fkiiwv773pwq05j7pqmiwoaj3et3l6yz8zcnft8hk3qo9ct4k4buaph1x
I received: 600
Here is your random string: 
iudhs4g14yh3wgg5sihbbz9sejld1mni4zt0120fnvj4r3ei6d77hco86nr4dyle7sgtl6bjh8y7e9lt8cjprurs356e1g603u88bn2yqexj1442jlw2q4vh4gw1j1kn2h60085wp9qd0wb5qqx427c110ck
I received: 600
Here is your random string: 
iudhs4g14yh3wgg5sihbbz9sejld1mni4zt0120fnvj4r3ei6d77hco86nr4dyle7sgtl6bjh8y7e9lt8cjprurs356e1g603u88bn2yqexj1442jlw2q4vh4gw1j1kn2h60085wp9qd0wb5qqx427c110ckckzs7768s13aef7i74zs24v0l8ftqcfypkqmkbr7bei753c6bwnl6or9ofv1
I received: 60
Here is your random string: 
iudhs4g14yh3wgg5sihbbz9sejld1mni4zt0120fnvj4r3ei6d77hco86nr4dyle7sgtl6bjh8y7e9lt8cjprurs356e1g603u88bn2yqexj1442jlw2q4vh4gw1j1kn2h60085wp9qd0wb5qqx427c110ckckzs7768s13aef7i74zs24v0l8ftqcfypkqmkbr7bei753c6bwnl6or9ofv1iwk5x448tvewpz5x5c5o0t8np
I received: 25
Here is your random string: 
iudhs4g14yh3wgg5sihbbz9sejld1mni4zt0120fnvj4r3ei6d77hco86nr4dyle7sgtl6bjh8y7e9lt8cjprurs356e1g603u88bn2yqexj1442jlw2q4vh4gw1j1kn2h60085wp9qd0wb5qqx427c110ckckzs7768s13aef7i74zs24v0l8ftqcfypkqmkbr7bei753c6bwnl6or9ofv1iwk5x448tvewpz5x5c5o0t8np113x2lro19aqtc78mloya2dv5ssl52ixeo7
I received: 35
Here is your random string: 

I received: 60
Here is your random string: 
rbx9lockccol46tfm0maxvr4pilvhi6aphnef3yiyspjq4eq1tbw7jnafmvxzgop5l0oxdvpma8b65cvmgudngmogfjmy416a42zmstqmjmggxjemdju3wd6ppa2yzgwr5mtjvwmmpx044v7g20suukbxgbrc5jr8xptjlrfzkfidv4ae4zq7x9yuza5ucoksovxx6vzohbrbye2chgp7m0oblmm2fya7tfrhib4y4d8t38xqe8h4o4avso264dstv2z8n4u
I received: 600
Here is your random string: 
h4quwywb0iq6zhovzh6vg295h03zimp3u3w07eytlqiz8yw7npku1aqf0mlc6ci9juj0ow763uuxze5unflpiw2fwf8v74m10wbetpypvi4xyh149ph41jofm1hvljz7dfs9wjbc73cm3rbhz2pylnk45ogg2lo7zp34hwqut955gswhetxtffaozqxua3t0
I received: 600
Here is your random string: 
tzq5zvwrql6fof4jouw99hmaq7n3hj0yxhllrbmaxqturrxz9bzwcdcvcupl095qzn8k6q9syk7yfgfaw65pb978q9zie56olv5ne89usr88d6j5crdyver8
I received: 600
Here is your random string: 
kcowv8wgl5szp2hn6kfm6orvqy0zy528s25me7xlajkjxxtf
I received: 600
Here is your random string: 
ahuc8s42pti6nyzl4s0j5oaz0k1u3s2va43ajckfi1dohuuu9c1eth7u2mc7ur7fnk4w1o4dlxk3gsdy14vlw1kka97rsfszigta8avsg8b7a2av2apuxjsfn83jka7blibzz528vu7cyxw2v0tn53dw7m0ixhdvi844xkbqwdw3hy2ja37e22zd4ac3od4nv1ifl1v8tya6xvd8hd4u2hzkrgyvpl2uc916dcdz9a131uptwnms1882jtnioy2xqcrjtlg7jtzwtjkdli04ogupsberp8oe8f2iu1mgse1ux723d2s3di87
I received: 600
Here is your random string: 
cynqeqsxywtox3dqwwioekt4i9tu1zagvsiin6adwkr42waqps15p2jvr39s5ztnuztjsqaxjr0diy3gwg0if39bhhqwawykz7adhdzsl6nsew3vokahxtbjc40jrz4p876ktry8fod3vzflb8eip5rx667pxqgedlhtupkfr13ytrvsy7lzpsn0wyl69qyp2pjyvbz6pvssd5oqmwtbszi6ycj4v35wcsom0nkxjjeo5s6o
I received: 600
Here is your random string: 
p3h2ycg25j1vnki31mx9eh4lidxicdx2m6g5sgnri9whwq188azmrnxxkf8vbqbx2lo65i9amsg65nn3vi2eobxkq0lw7vmii7lpamravb8j79r4sp4mc79nsz271ps9eifhh3xdcey9yvmltzs0ns0le1un67e9ibz3qnl6
I received: 600

Why are you bothering to store the string of random characters?

Get rid of the String class and use char arrays instead. Strings waste memory and you can't afford it. To answer your question, check strcat().

I am looking to send a packet of random data across my xbees; I want to test to see how quick they work sending data as speed and accuracy is of importance in my application. I'll then use an md5 hash on both sides of sending and receiving to see if they match correctly without error.

I am doing random data to test to see if it works with many different types of data sequences.

It's a pseudo-random number generator; there's no need to store the string - even if you need the same string again, simply re-seed the the RNG with the same value and regenerate the original

I will not need the same string again. I will change to working with characters as recommended. I'll update my code here in a few whether it is working or not.

If I understand your code correctly you are supplying me with a random character.

In a more efficient manner than letters[random(0, 36)].

How do I then append that character to the end of a string?

strcat(), if you really mean string. += if you really meant String.

   numBytes = Serial.parseInt();
    if(numBytes > 0)
    {
      for(i = 0; i<numBytes; i++)
      {
         byte randomValue = random(0, 36);
         char letter = randomValue + 'a';
         if(randomValue > 26)
           letter = (randomValue - 26) + '0';
         randString += letter;
      }

I will not need the same string again. I will change to working with characters as recommended. I'll update my code here in a few whether it is working or not.

You will need a static array. You will then need to make sure that the value read from the serial port is not greater than the size of the array (minus 1).

TheHobbyist:
Hello All, I am looking to create/obtain a random alphanumeric generator for arduino. I searched the forums and online for a solution that works in the arduino environment but came up short, so I decided to write my own. Below is my code. If you know of another random alphanumeric generator that works in the arduino space can you please just provide it? It is hard to explain exactly how my code acts. It is interesting to see how it works, as it is anti intuitive of what I'd/you'd expect. The size of the random string will be between 0 and 16000 as I will be sending over packets up to 16M and want to test it first with random bit to check for bit errors. I believe the reason I seeing what I am seeing is because of the max memory on the arduino. Please take a look and let me know what you think. Thank you.

int numBytes = 0;

int i = 0;
int j = 0;
String letters[40] = {"a", "b", "c", "d", "e", "f","g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
String randString = "";

void setup() {
  Serial.begin(230400);
}

void loop() {
  if(Serial.available())
  {
    numBytes = Serial.parseInt();
    for(i = 0; i<numBytes; i++)
    {
    randString = randString + letters[random(0, 40)];
    Serial.println(randString);
    }
    Serial.println("Here is your random string: ");
    Serial.println(randString);
    Serial.print("I received: ");
    Serial.println(numBytes);
    delay(1000);
  }
}

Thanks for posting your code.
Was puzzled why you checking using parseInt and run some tests to discover an interesting bug in Serial.available.
Thanks

Thank you for your help. I decided to stick with my string. I got it working. I just needed to clear out my string at the end. I understand that I am not allocating memory to the best I can, but for now I just want to move on. I spent to long writing this code. Thank you again. This was very helpful and I am sure it will continue to be helpful to future readers.

int numBytes = 0;
int i = 0;
int j = 0;

String letters[]= {"a", "b", "c", "d", "e", "f","g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
String randString = "";

void setup() {
  Serial.begin(230400);
}

void loop() {
  if(Serial.available()) 
  {
    numBytes = Serial.parseInt();
    if(numBytes > 0)
    {
      for(i = 0; i<numBytes; i++)
      {
       randString = randString + letters[random(0, 36)];
      }

    Serial.println("Here is your random string: ");
    Serial.println(randString);
    Serial.print("I received: ");
    Serial.println(numBytes);
    delay(1000);
    randString = "";
    }
  }
}

and run some tests to discover an interesting bug in Serial.available.

In the absence of any proof, user error seems far more likely. Serial.available() simply subtracts the location of the tail pointer from the head pointer. Either the two pointers point to the same place, and the buffer is empty, or they don't, and the difference is the number of characters in the buffer.

OP: Your solution takes 5786 bytes of memory and doesn't work as advertised. I've thrown together an alternative solution using Paul's suggestions and getting rid of the String class, which you are using as a crutch, and the code size drops to 3470 bytes -- a memory savings of about 40%. It also has the advantage that it works:

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0));    // Seed RNG
}

void loop() {
  byte randomValue;
  char temp[5];
  char letter;
  char msg[50];     // Keep in mind SRAM limits
  int numBytes = 0;
  int i;
  int charsRead;
  
  if(Serial.available() > 0) 
  {
    charsRead = Serial.readBytesUntil('\n', temp, sizeof(temp) - 1); // Look for newline or max of 4 chars
    temp[charsRead] = '\0';   // Now it's a string
    numBytes = atoi(temp);
    if(numBytes > 0)
    {
      memset(msg, 0, sizeof(msg));
      for(i = 0; i < numBytes; i++) {
        randomValue = random(0, 37);
        msg[i] = randomValue + 'a';
        if(randomValue > 26) {
          msg[i] = (randomValue - 26) + '0';
        }
      }
      Serial.println("Here is your random string: ");
      Serial.println(msg);
      Serial.print("I received: ");
      Serial.println(numBytes);
      delay(1000);
    }
  }
}

It also has the advantage that it works:

Well, until random() returns 36, anyway. The upper limit for the random() call should be 36.

My code works, you probably didnt change your baud rate in your serial terminal

Vaclav:
Thanks for posting your code.
Was puzzled why you checking using parseInt and run some tests to discover an interesting bug in Serial.available.
Thanks

Maybe it's another REAL issue BUG like this one.

I'm deeply worried about an outbreak of this

AWOL:
I'm deeply worried about an outbreak of this

+1

Well, until random() returns 36, anyway. The upper limit for the random() call should be 36.

Not my bad, since I copied the code from your post #1. :slight_smile: