See the code in action on Tinkercad
/* * Uuid Version 4 * * UUIDs are unique numbers that are used for identifying individual units, * functions, programmes, or whatever you want to tag. * * In this demo, press the Arduino Reset button to generate a new number. * * UUIDs can be assigned sequentially from allocated blocks of numbers, but * they are most powerful when randomly assigned. UUIDs are such big numbers * that, for all effective purposes, no two numbers will ever match. * * UUIDs are particularly useful in web-aware devices, or radio networks. * * For a discussion of the use of UUIDs, see * http://en.wikipedia.org/wiki/Universally_Unique_Identifier * * For implementation details of UUIDs, see * http://tools.ietf.org/html/rfc4122 TrueRandom library by Peter Knight, Tinker.it! 2010 http://code.google.com/p/tinkerit */ #include <EEPROM.h> class TrueRandomClass { public: int randomBit(void); char randomByte(void); void memfill(char* location, int size); void uuid(uint8_t* uuidLocation); private: int randomBitRaw(void); int randomBitRaw2(void); }; extern TrueRandomClass TrueRandom; int TrueRandomClass::randomBitRaw(void) { uint8_t copyAdmux, copyAdcsra, copyAdcsrb, copyPortc, copyDdrc; uint16_t i; uint8_t bit; volatile uint8_t dummy; // Store all the registers we'll be playing with copyAdmux = ADMUX; copyAdcsra = ADCSRA; copyAdcsrb = ADCSRB; copyPortc = PORTC; copyDdrc = DDRC; // Perform a conversion on Analog0, using the Vcc reference ADMUX = _BV(REFS0); #if F_CPU > 16000000 // ADC is enabled, divide by 32 prescaler ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS0); #elif F_CPU > 8000000 // ADC is enabled, divide by 16 prescaler ADCSRA = _BV(ADEN) | _BV(ADPS2); #else // ADC is enabled, divide by 8 prescaler ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0); #endif // Autotriggering disabled ADCSRB = 0; // Pull Analog0 to ground PORTC &=~_BV(0); DDRC |= _BV(0); // Release Analog0, apply internal pullup DDRC &= ~_BV(0); PORTC |= _BV(1); // Immediately start a sample conversion on Analog0 ADCSRA |= _BV(ADSC); // Wait for conversion to complete while (ADCSRA & _BV(ADSC)) PORTC ^= _BV(0); // Xor least significant bits together bit = ADCL; // We're ignoring the high bits, but we have to read them before the next conversion dummy = ADCH; // Restore register states ADMUX = copyAdmux; ADCSRA = copyAdcsra; ADCSRB = copyAdcsrb; PORTC = copyPortc; DDRC = copyDdrc; return bit & 1; } int TrueRandomClass::randomBitRaw2(void) { for(;;) { int a = randomBitRaw() | (randomBitRaw()<<1); if (a==1) return 0; // 1 to 0 transition: log a zero bit if (a==2) return 1; // 0 to 1 transition: log a one bit // For other cases, try again. } } int TrueRandomClass::randomBit(void) { for(;;) { int a = randomBitRaw2() | (randomBitRaw2()<<1); if (a==1) return 0; // 1 to 0 transition: log a zero bit if (a==2) return 1; // 0 to 1 transition: log a one bit // For other cases, try again. } } char TrueRandomClass::randomByte(void) { char result; uint8_t i; result = 0; for (i=8; i--;) result += result + randomBit(); return result; } void TrueRandomClass::memfill(char* location, int size) { for (;size--;) *location++ = randomByte(); } void TrueRandomClass::uuid(uint8_t* uuidLocation) { // Generate a Version 4 UUID according to RFC4122 memfill((char*)uuidLocation,16); // Although the UUID contains 128 bits, only 122 of those are random. // The other 6 bits are fixed, to indicate a version number. uuidLocation[6] = 0x40 | (0x0F & uuidLocation[6]); uuidLocation[8] = 0x80 | (0x3F & uuidLocation[8]); } TrueRandomClass TrueRandom; byte uuidNumber[16]; // UUIDs in binary form are 16 bytes long void printHex(byte number) { int topDigit = number >> 4; int bottomDigit = number & 0x0f; // Print high hex digit Serial.print( "0123456789ABCDEF"[topDigit] ); // Low hex digit Serial.print( "0123456789ABCDEF"[bottomDigit] ); } void printUuid(byte* uuidNumber) { int i; for (i=0; i<16; i++) { if (i==4) Serial.print("-"); if (i==6) Serial.print("-"); if (i==8) Serial.print("-"); if (i==10) Serial.print("-"); printHex(uuidNumber[i]); } } void printUuidNum(byte* uuidNumber) { int i; for (i=0; i<16; i++) { printHex(uuidNumber[i]); } } void array_to_string(byte array[], unsigned int len, char buffer[]) { for (unsigned int i = 0; i < len; i++) { byte nib1 = (array[i] >> 4) & 0x0F; byte nib2 = (array[i] >> 0) & 0x0F; buffer[i*2+0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA; buffer[i*2+1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA; } buffer[len*2] = '\0'; } void setup() { Serial.begin(9600); // Generate a new UUID TrueRandom.uuid(uuidNumber); Serial.print("The UUID number is "); printUuid(uuidNumber); Serial.println(); } void loop() { }