Що є найменшим та найпростішим насінням для генератора випадкових чисел?


40

Невеликий мікроконтролер (8-бітний Atmel) керує низкою вогнів, щоб представити світлове шоу з безліччю фантазійних рандомізованих послідовностей світла.

Підходящий псевдо-RNG прекрасно виконує свою роботу, але я шукаю гарне насіння для цього. Насіння буде необхідне, тому що якщо хтось одночасно вмикає кілька таких пристроїв, це не буде добре виглядати, якщо всі вони генерують однакові послідовності ефектів, поки вони повільно не відшаровуватимуться через невеликі відмінності в своїх окремих джерелах тактових годин.

Дуже хороший метод засіву псевдо-РНГ, який я часто використовував, можливий у випадку, коли пристрій потрібно запустити натисканням кнопки або перемиканням перемикача. Як тільки мкк увімкнено, можна запустити дуже швидкий таймер, і значення цього таймера заповнює RNG, як тільки кнопка натиснута вперше.

Проблема в тому, що в цьому сценарії немає кнопок. Програма повинна запускатися, як тільки пристрій увімкнено.

Місце на друкованій платі вкрай обмежене (не більше ніж декілька найменших SMD деталей можуть вміститися), тому я шукаю найменше і найпростіше можливе рішення. Тому я виключаю химерні рішення, такі як справжнє обладнання для RNG, радіоприймачі тощо.

У мене є 16-бітний таймер-лічильник в процесорі та невикористаний портпін, який має доступ до АЦП.

Моє поточне рішення - просто використовувати резистор (якомога неточніше), щоб забезпечити приблизно половину напруги живлення на контактний контактний АЦП, і засіяти RNG з першим значенням перетворення AD. Однак в даний час більшість 10% резисторів мають неточність набагато менше 1% (було б цікаво уявити обличчя постачальника, коли я їм кажу, що ми хочемо, щоб резистори SMD найгіршої якості вони могли знайти), тому є дуже високий шанс кілька одиниць, починаючи з одного насіння.

Кращою альтернативою було б зробити кілька перетворень та створити значення з найменш значущих бітів цих вимірювань. Однак я раніше використовував АЦП цього типу µc і знаю, що це дуже точно. Тут може допомогти запуск АЦП на максимально швидкій швидкості.

Хтось має кращу пропозицію? Насіння не вимагає ідеального рівномірного розподілу, але чим рівномірніше розподіл, тим краще. 16-бітове насіння з ідеально рівномірним розподілом було б занадто хорошою мрією, щоб бути правдою, але я думаю, що на півдорозі пристойний розподіл на 5 або 6 біт може бути достатнім.


12
"було б весело уявити собі обличчя постачальника, коли я їм кажу, що ми хочемо, щоб резистори SMD найгіршої якості вони могли знайти" - було б навіть смішніше, щоб значення цього резистора не було визначено в схемі, і говорили про люди на виробництві, що цю частину потрібно спаяти вручну після того, як друкована плата вийде з машини для розміщення, з відро, де ми змішали разом усі значення резистора. - Тому що це не РНГ, яку я шукаю, а насіння . Тож якщо воно генерує одне і те ж значення майже кожного разу, коли це не так вже й погано, важливіше бути різними на різних пристроях.
vsz

8
Чому б не записати випадкове значення у сховище EEPROM під час виробничого програмування? Таким чином, ви можете використовувати найпопулярніший RNG, який вам подобається, оскільки він буде лише у виробничих програмістах, а не на кінцевих пристроях. (Заслуга @immibis: ваш «трохи інший файл програмного забезпечення» дав мені ідею.)
Calrion

2
Тож просто щоб бути зрозумілим на 100%, проблема полягає в тому, що вони можуть почати в одній послідовності, а не в тому, що вони можуть з часом розійтися, правда?
весілля

2
Вибір вашої РНГ має значення: деяким потрібні якісні насіння, а іншим - ні. Наприклад, для Xorshift будь-яке насіння, окрім 0, буде працювати однаково добре. Навіть невелика різниця в початковому насінні призведе до зовсім іншого вихідного положення в циклі RNG.
курйозданні

3
Ви можете комбінувати всі відповіді АЦП зі статистикою та термінами для ще більшої випадковості. Наприклад, виміряйте, скільки кліщок процесора знадобиться, поки ви не візьмете N зразків, де 3 нижніх LSB - 101, і M зразків, де нижні 3 LSB - 110. Розкрийте це поняття за бажанням.
wjl

Відповіді:


24

Покладіть паралельний резистор та конденсатор між штифтом A / D та землею. Зробіть резистор досить високим, бажано набагато вище вимоги імпедансу вхідного сигналу для A / D. Зробіть час RC постійним, можливо, приблизно 10 мкс. Наприклад, 100 кОм і 100 пФ звучать як гарна комбінація.

Щоб отримати значення з деякою випадковістю, наведіть штифт на деякий час, а потім встановіть його на високий опір і зробіть читання A / D через кілька мкс пізніше. Особливо, якщо ви неправильно зловживаєте часом збору A / D, напруга, яку він буде бачити, буде залежати від значень R і C, струму витоку штифта, іншого шуму поблизу та температури.

Візьміть низький біт або два біти і повторіть по мірі необхідності, щоб отримати будь-яку кількість випадкових біт.

Для більш випадкової картини виконайте цю процедуру періодично і введіть низький біт результату A / D в генератор випадкових чисел, який ви вже використовуєте.


Це добре звучить. Не забудьте перевірити вхідний опір на АЦП - серія Atmega8 має аналоговий вхідний опір 100Meg, що робить значення резистора Оліна трохи низьким.
stefandz

3
@stef: Вхідний опір і імпеданс сигналу, необхідний для правильного перетворення, - це дві різні речі. Так, вхідний опір дуже високий через те, що він CMOS. Однак існує максимальний межа імпедансу для сигналу, який дозволяє йому заряджати зразок і утримувати кришку протягом визначеного часу, а також долати будь-який витік штифта.
Олін Латроп

2
Вибачте, з вашої відповіді я подумав, що ви посилаєтесь на вхідний опір на відміну від специфікації джерела імпедансу. 10k - вказаний максимальний імпеданс джерела Atmega8, тож ваша відповідь не вказана. Для довідки, кришка S / H всередині 14pF, на випадок, коли хтось зацікавився.
stefandz

2
@stef: я змінив відповідь, щоб зробити це більш зрозумілим.
Олін Латроп

Ви пропустили фазу місячних та банківські канікули. Також рукою махає корисним доповненням, особливо якщо низький C і недостатньо захищений екраном.
Рассел Макмахон

23

Деякі можливі варіанти:

  1. Попередньо запрограмуйте унікальну серійну адресу для кожного пристрою. Якщо у вас досить хороший алгоритм RNG, то навіть послідовний список послідовних адрес дасть дивовижні результати.

  2. Залежно від вашого MCU / налаштування, у вас можуть бути два різних тактових джерела для системного годинника та вхід лічильника таймера / лічильника таймера. Якщо один / обидва з них мають значну дисперсію, ви можете використовувати це для отримання відповідного іншого насіння. Ось приклад, який я написав, який використовує внутрішній сторожовий таймер Arduino та зовнішній системний годинник XTAL .

  3. Використовуйте транзистор BJT і побудуйте підсилювач, що залежить від бета-версії. Це можна прочитати з АЦП для насіння.

  4. Конденсатори / індуктори зазвичай задаються набагато гіршими, ніж резистори. Ви можете побудувати якусь схему фільтру (RC, RL, LC) з ними і виміряти вихід за допомогою АЦП.


5
Я голосую за варіант 1, це рішення з нульовим підрахунком частини, яке призведе до того, що послідовності ніколи не збігаються. Серійний номер та генератор RND можуть сказати, що 16 біт, завдяки чому будь-які пристрої мають незначний шанс імітувати чужий зразок.
KalleMP

1
Мені також подобається рішення одне. Якщо ви користуєтеся простим алгоритмом хешування, вам слід добре, навіть якщо у вас є послідовні порядкові номери.
magu_

6
Приємна річ у варіанті 1 - це те, що деякі пристрої мають вбудовані серійні номери (як правило, мікросхеми, пов'язані з мережею / радіочастотою), тому вам навіть не потрібен окремий крок для запису серійних номерів
slebetman

3
Навіть сміттєвий СПГ, як LCG , "дасть дивовижні результати для послідовного списку серійних адрес" . Я також голосую за 1.
BlueRaja - Danny Pflughoeft

3
Якщо у вас є джерело часу, то використання цього в якості основи для перемикання насіння допоможе компенсувати речі між прогонами. Поєднайте це з серійною адресою / номером або MAC-адресою, якщо у вашому пристрої є така, і ви також виправите відповідність між пристроями. Я бачив якесь програмне забезпечення, яке наполегливо зберігає якесь або кожне випадкове число, створене для використання як насіння, навіть після перезавантаження. Якщо ваші пристрої мають різний час роботи, вони повинні відхилятися.
TafT

8

Неініціалізована пам'ять

Ви можете спробувати використовувати неініціалізовану пам'ять у мікроконтролері. Хитрість полягає в тому, щоб знайти біти, які мають найбільш «врівноважені» шльопанці, і насправді є випадковими. Процедура полягає в тому, щоб прочитати всю пам'ять, скинути і повторити кілька разів, щоб виміряти, які біти справді випадкові. Тоді ви використовуєте цю карту, щоб прочитати достатню кількість випадкових бітів для насіння PRNG або LFSR!

Цей метод повинен дати вам випадкові насіння, навіть з однаковим обладнанням, більше деталей (та посилань) доступні в цій статті про хакінг

Мені подобається цей метод, тому що він не потребує додаткових схем чи штифтів; ваш AVR вже має таран, вам просто потрібно знайти нестабільні (випадкові) біти. Також процедура картографування може бути автоматизована; ви можете застосувати один і той же код і процедуру до кожного пристрою і мати справді випадкові результати!


1
Вам не потрібно розбиратися, які біти є випадковими. XOR-ing всіх байтів дасть вам випадковий результат, навіть якщо лише 8 біт випадкові. І як показує малюнок, фактичні значення можуть не бути випадковими у часовому сенсі, вони достатньо унікальні - саме для цього нам тут потрібно.
MSalters

1
Якщо ви зможете знайти PRNG, який дозволяє "перемішати" ентропію, то це може бути навіть кращим, ніж варіант XOR-тоді-насіння. Ітерайте через неініціалізовану пам'ять і змішайте в байтах до PRNG. Наприклад , побачити мою функцію бібліотеки мікшування simplerandom C .
Крейг МакКуїн

Це не дасть вам випадковості криптовалюти.

@CamilStaps, звичайно, не буде.
Навін

1
Це не вийде. Неініціалізована пам'ять - це невизначена поведінка, якщо я маю операційну систему і не маю ніякого контролю над тим, яка частина пам'яті буде призначена моїй програмі і що там було раніше. На мікроконтролері без ОС це не так. Особливо це стосується AVR, оскільки там вся оперативна пам'ять буде нульовою, якщо пройде достатньо часу, щоб конденсатори спорожніли від споживання струму в режимі коричневого відключення.
vsz

7

Що я зробив для MP3-плеєра з випадковими можливостями, це просто використовувати інше послідовне насіння при кожному включенні живлення. Я почав з 1 і зберігав це в EEPROM, щоб на наступному циклі живлення я використовував 2 і т.д. Це було на ATMEGA168. Як зазначає helloworld922, навіть просте послідовне насіння генерує абсолютно різні псевдовипадкові послідовності.

Я використав один з генераторів лінійних конгруентних випадкових послідовностей, це дає рівномірний розподіл.

int i;
seed = seed * 2053 + 13849;
i = (seed % max) + 1;  // max is the maximum value I want out of the function

Звичайно, якщо ви хочете, щоб кілька одиниць мали різні послідовності, хоча вони, можливо, мали однакову кількість силових циклів, тоді вам потрібно щось почати випадковим чином.

Це можна зробити будь-яким із методів, запропонованих іншими плакатами. Один із способів, на який я можу подумати, чи міг би використовувати перехід нульового струму змінного струму, що йде в процесор, якщо він у вас є (наприклад, для управління фазовою лампою)? Це може бути використане для вибірки таймера під час першого схрещування після включення живлення, а потім його використання як насіння.

Чи є кнопки на пристрої для вибору режиму тощо? Якщо так, ви зможете пробувати лічильник лічильників у перший раз після натискання кнопки після програмування MCU, ви можете спочатку генерувати випадкове насіння та зберігати його в EEPROM. Кожне включення живлення після цього моменту використовує збережене насіння.


5

АЦП - дуже гарне джерело для випадкових випадків.

Вам не потрібно покладатися на допуски резисторів. Будь-який резистор буде генерувати тепловий шум , і той же фізичний ефект буде вносити шум в АЦП при виконанні всіх етапів вибірки та перетворення. (Лист даних розповість про кількість шуму та про те, які налаштування конфігурації є найгіршими / найкращими.)

Ви не повинні залишати штифт ADC плаваючим; це може дати напрузі плавати занадто далеко, і ризикує наситити вхід.
(Багато MCU дозволяють використовувати щось на зразок половини напруги живлення як вхід АЦП для калібрування. Це економить зовнішній резистор і все ще видає шум. Знову дивіться таблицю про найгіршу / найкращу конфігурацію.)

Вам не потрібно покладатися на один вимірювання АЦП; ви можете комбінувати кілька вимірювань за допомогою простої хеш-функції або контрольної суми (CRC буде достатньо). Якщо вам потрібно негайно почати використовувати RNG, ви можете згодом поєднати результат ADC з поточним насінням RNG.


2
Я не впевнений, що шум Джонсона підходить у цій програмі; У режимі STP 10-мегарезисторний резистор понад 10 кГц пропускає 40uVшум Джонсона. Вам знадобиться> 14-бітний АЦП або ланцюг підсилювача для розумного вимірювання цього.
helloworld922

STP насправді не має значення. Температуру особливо можна навмисно підвищити, але додаткові 60 градусів над STP - це лише 10% зайвого шуму.
MSalters

1
Аналогічним підходом було б використання шуму пострілу в діоді. en.wikipedia.org/wiki/Noise_generator#Shot_noise_generators
teambob

2

Чи можете ви зберегти насіння від сеансу до сеансу? Якщо так, то чи можливо включити кожну одиницю на якийсь випадковий проміжок часу після створення? Таким чином всі одиниці будуть поставлятися з попередньо встановленими насінням, які навряд чи будуть однаковими.

Інша думка: як зв’язати кілька одиниць разом, щоб вони ввімкнулися одночасно? Якщо вони в серії, додайте якийсь конденсатор, щоб (n + 1) пристрій розпочав кілька тактових циклів після n-го пристрою. В ідеалі конденсатори розряджатимуться дуже швидко при відключенні пристрою, тому з кожним запуском / перезапуском виникає більший проміжок між послідовностями.

Якщо вони паралельно, ви все одно можете трохи рандомізувати час запуску. Я припускаю, що є якась фільтрація потужності за допомогою конденсаторів. Якщо так, виготовлення пристроїв з дещо різними схемами фільтрації призведе до запуску кожного пристрою в дещо інший час, викликаючи розбіжність після декількох перезапусків.

Варіант цього варіанту полягає в тому, щоб додати дисперсію до сигналів годинника, якщо це можливо. Різниця в тактовій частоті на 0,1% може мати незначний вплив на світлове шоу, змінюючи швидкість, ви досить швидко переходите по таблиці PRNG.


1
можливо, підключіть велику заливку до аналогового штифта та візьміть деякі показання "мережевого гуду", щоб засіяти RNG.
Ясен

1
@Jasen, всі пристрої, підключені до одного і того ж розширення, будуть бачити однаковий гуркіт мережі.
Ян Рінроуз

2

Якщо ви працюєте на внутрішньому "каліброваному" джерелі годинника. Чи не зможете ви зберегти насіння через деякий час, бажано в EEPROM. Годинник буде дрейфувати, і він буде відрізнятися від одиниці до одиниці. Щоб зберегти нове значення через деякий час (можливо, кожні 10 хвилин або близько того, або через час, який достатньо короткий, щоб відбутися протягом нормального часу роботи пристрою. Чим довше пристрій увімкнено, тим більше шансів зберегти його) "інше" значення в EEPROM.

Також виконайте стрибок раз у раз (не часто) та перезавантажте, коли пристрій увімкнено (збережіть це нове значення в EEPROM).


2

Що щодо розширення вашої оригінальної ідеї перетворення AD на основі різного резистора шляхом додавання LDR або термістора? (Перший повинен мати можливість "дивитися" назовні, я не знаю, чи це можливо; але зміна світла може бути вищою, ніж коливання температури серед пристроїв, запущених приблизно в один і той же час приблизно в тому самому місці. ..)


1
Термістори входять із ще однією корисною властивістю. Кілька серій від більшості виробників мають величезну дисперсію та неточність. Це ще більше «покращить» результат.
Ariser

1

2 потенційних рішення, обидва припускаючи, що вам потрібно унікальне насіння на одиницю.

  1. Якщо ви прошиваєте свої одиниці один за одним на заводі, шістнадцятковий файл може бути програмно модифікований деяким проміжним сценарієм програміста. Якщо він керується ПК, ви можете замінити ініціалізацію змінної з датою та часом. Гарантована унікальність для кожного блоку!

  2. Провідні пристрої Dallas 1 використовують лише один штифт, і кожен має унікальний серійний номер 64 біт. Ви можете використовувати це як насіння.


1
Мені подобаються 2, але, на жаль, деталі DS все досить дорогі.
Ariser

Не використовуйте часові позначки виробництва для випадковості крипто-якості, це передбачувано.

2
@CamilStaps Для застосування ОП криптоякісність не потрібна
Hagen von Eitzen

1
@HagenvonEitzen правда, але до цього питання можуть підійти інші, шукаючи випадковості крипто-Q, тому варто згадати.

4
@CamilStaps Зітхання , здається , що ви відмовилися від людства :) Це дійсно дуже вимоглива очікувати від кого - то , хто хоче використовувати відповідь від electronicsSE для криптографічних цілей , щоб вони по крайней мере , досить уважні , щоб читати це питання передбачається відповісти ? Насіння "16 біт" або "5 o5 6 біт" не є крипто-Q, навіть якщо їх породжує купа котів Шредінгера :)
Hagen von Eitzen

1

Ви можете залишити плаваючий контактний АЦП, щоб живити генератор випадкових чисел (RNG) захопленим шумом. Його має бути достатньо для генерації насіння або навіть використання його як генератора RNG.

Не забувайте використовувати мінімально можливий час конверсії.

Іншим рішенням може бути генератор шуму, застосований до штифта АЦП.


2
Я зроблю кілька вимірювань, але якщо я пам'ятаю правильно, плаваючий штифт АЦП читається 0або наближається до нього 0. Я ще раз перевірю це, щоб побачити, чи це так.
vsz

1
Мене цікавить, чи читається він, 0коли пливе?
Бенс Каулікс

2
Проблема полягає в тому, що це може працювати на дошці розробок і вийти з ладу у кінцевому продукті.
vsz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.