Most microcontrollers don’t have a random function. Random functions are not truly random, they’re actually a complex mathematical formula that results in a number that “seems” random. That can take up lots of processing time, so it’s usually the first function to go when writing a microprocessor language.
In fact, most of what you do in programming physical computing projects is to figure out how to deal with the world’s natural randomness and make it look smooth. A photoresistor read through an analog-to-digital converter, for example, will never give you a nice steady number, it always fluctuates with tiny changes in lighting that your eye can’t see. Your consciousness is a great leveller for the sensors that are your eyes, ears, skin, nose, and taste buds When you move a photoresistor from one room to another, your readings will be totally different, and all of a sudden, you have to re-calculate what is “average” and what constitutes the lighting change that you want. And that’s just one of many examples. The fact is, data from sensors is filled with the noise of the real world. Plan for it in advance.
Given that you can’t avoid all that noise, you can use the real world to your advantage. One simple example is to use the random static electricity generated by people, radio waves, etc. Try this: stick a bare wire on an analog input of your microcontroller. Make it a long one, say, a foot or more. Strip off the insulation. Coil it if you want. Don’t attach the other end to anything. Program the chip to get the value of the analog in, and debug the result. As it’s running, touch the antenna. The numbers are pretty random, and more so when you touch it. That’s because you’re reading micro-voltage changes due to anything in the room that generates an electrical signal: you, a TV monitor, a cell phone, etc. The bare wire is an antenna for your chip. Use its results as a random number.
Want it to be more random? Design your project in such a way that, when the user touches the wire, you read the analog input on it. Perhaps the wire is physically next to a button the user presses, and when they press the button, they also touch your wire (because they can’t avoid it). So wherever you getPin() to read the button, you read the input again to get a new random number.
How about using time as a random number? Measuring the time in between events like button pushes, in milliseconds, will offer a highly random number. Even when we think we’re being very regular physically, we’re off by a number of milliseconds each time
Most of the time when you use a random function in a program, it’s because you’re trying to duplicate or mimic the randomness of the real world. You want a roll of the dice, you want a roulette ball falling on a number, you want a shuffled card, you want a phonebook flipped open to a random page, you want a finger pointed to a random name on that page. Those are hard things to get when the only input to the chip you have is a keyboard and a mouse. Stop to ask yourself what physical act would cause your ideal random number. When you’ve got the capacity to sense other things in the real world, it’s possible to take advantage of the actual things you would otherwise mimic onscreen. So every time I think I need a random number, I ask myself if there is a way to get that number from the physical system I am building. If it’s a game, how about letting the physical position of the gameboard generate my random number. A light sensor on the side will tell me something about the room it’s in. An accelerometer inside it will tell me if the user’s carrying it or if it’s stable on a table. An FSR underneath will tell me its weight, and if a user is pressing on it. Many of these properties are subject to change as the user interacts with the object. The chance that they will be exactly consistent each time you need a random number during the course of the experience is very slim.
This demonstrates one of the fundamental differences about thinking as a programmer before and after physical computing. Before, you are limited to what the programming environment gives you. After, you always factor in the physical design, and this allows you countless ways around the limitations of any programming environment.