Как да генерирам ефективно случайни числа в микроконтролер?

Как да генерирам ефективно случайни числа в микроконтролер? Има ли общи насоки или конкретен бърз метод?


person Donotalo    schedule 13.10.2009    source източник
comment
Колко произволност ви трябва? Скоростта ли е най-важното желание тук или непредсказуемостта е най-важна? Има много различни алгоритми за генериране на псевдослучайни числа, насочени към различни приложения с различни цели. Една игра, например, няма да се нуждае от непредсказуемост толкова, колкото да речем, нещо, което генерира кодове за криптиране с висока степен на сигурност.   -  person Amber    schedule 13.10.2009
comment
Имам нужда от скорост. Няма криптографско изискване.   -  person Donotalo    schedule 13.10.2009


Отговори (8)


Можете да генерирате псевдослучайни числа чрез манипулиране на битове чрез симулиране на ЛИНЕЕН РЕГИСТЪР ЗА ИЗМЕСТВАНЕ С ОБРАТНА СВЪРЗКА

Тогава въпросът става "колко бита искате да симулирате?"

Уикипедия има известна информация.

person pavium    schedule 13.10.2009
comment
Всеки път, когато микроконтролерът се нулира, ще получавам едни и същи произволни числа. Как мога да избегна това? С други думи, как мога да задам произволно семе? - person Donotalo; 13.10.2009
comment
Нямате часовник за реално време на вашия контролер? Това може да действа като семе. - person Will Hartung; 13.10.2009
comment
Имаме RTC, но е разумно решение да не го използваме. Ние симулираме RTC чрез фърмуер. Благодаря за коментара Вторият брояч на фърмуера може да се използва като семе. - person Donotalo; 13.10.2009
comment
Избран като най-добър отговор, защото открих, че LFSR отнема най-малко време за внедряване и също така е бърз. Използвам статична стойност, която да използвам като начална стойност, защото нашите устройства едва ли ще бъдат нулирани. Когато възникне нулиране, няма значение дали произвежда същите произволни числа. Началната стойност 0xAC дава период от повече от 10^8. - person Donotalo; 13.10.2009
comment
Избирането на правилното семе за правилния битов модел ще ви даде максимален LFSR, който ще генерира всички числа в битовия модел с изключение на 0. - person plinth; 13.10.2009

Обикновено се генерират псевдослучайни числа, а не действителни произволни числа, въпреки че и двете са възможни с различни скорости.

Има две общи категории в зависимост от това дали последователността ще се използва за криптографски цели. Основното разграничение е дали познаването на едно число в последователността позволява предсказване на следващото. RNG с общо предназначение не се притесняват дали познаването на алгоритъма би позволило на наблюдател да дублира последователността и те работят доста по-бързо.

Типичен RNG алгоритъм с общо предназначение е Mersenne Twister. Има много публични реализации на различни алгоритми. Вижте тук за един .

Ако MT изисква твърде много памет, полуприличен резервен вариант е линейният съгласуван генератор. (MT е изобретен едва през 1997 г.) Този генератор има определени проблеми, но не изисква почти никаква памет, почти никакъв код и е изключително бърз. Реализациите са навсякъде и това беше разгледано подробно в Получисловите алгоритми на Knuth.

За да заредите всеки RNG, ще ви трябва източник на ентропия, вижте http://en.wikipedia.org/wiki/Entropy_(computing) (Забележка: SO се обърква относно () в тази връзка.) Това обикновено се извлича от времеви събития, които процесорът може да наблюдава, като натискане на клавиши (предполагам, че няма да работи за вас) прекъсвания и пристигащи пакети. Часовникът за реално време често е приемлив източник, ако поддържа собственото си състояние, тъй като рестартирането рядко се синхронизира в някаква последователност.

person DigitalRoss    schedule 13.10.2009
comment
Тези RNG се нуждаят от семена, за да работят. Всеки път, когато микроконтролерът се нулира, ще получавам същия набор от произволни числа. - person Donotalo; 13.10.2009
comment
Аха, добър въпрос. (Получаваме основни RNG въпроси тук на SO през цялото време, така че ни извинете, че рефлексивно изстреляхме основния отговор. :-) Както и да е, актуализирах отговора си. Ще направя нова актуализация след минута... - person DigitalRoss; 13.10.2009
comment
Mersenne Twister използва пространство на състоянието, което е твърде голямо за микроконтролери. - person starblue; 13.10.2009
comment
Повечето микроконтролери имат ADC, които могат да се използват като източници на ентропия. Запазете само най-малко значимите шумни битове. - person endolith; 07.03.2012
comment
Почти всеки приличен поточен шифър може също да се използва като RNG, напр. Salsa20 (или някой от други eSTREAM шифри) (зареждането остава проблем...) (Изискванията за памет вероятно са непрактични за повечето 8-битови устройства) - person Gert van den Berg; 18.04.2018

можете да съхранявате семе в EEPROM и когато устройството се стартира, можете да увеличите семе и да го съхраните отново. Така че при всяко рестартиране ще имате различно произволно число.

person Igor    schedule 03.12.2012

Ако имате достъп до ADC, тогава можете да прочетете най-малко значимия бит от него и да го използвате като семе за генератор на псевдослучайни числа, както други са публикували. Очевидно ще трябва да прочетете повече от един бит от ADC, така че са необходими многократни четения, което може да отнеме известно време. Но трябва да направите това само веднъж, например при стартиране, и след това да използвате по-бърз PRNG, за да генерирате нови произволни числа.

Много вградени устройства имат вграден ADC, например фамилията ATMega от Atmel.

person Marius    schedule 13.10.2009
comment
За съжаление ADC в ATMegas е твърде стабилен. Дори LSB не се променя при много показания. skemman.is/stream/get/1946/10689/25845/ 1/ardrand.pdf. - person endolith; 24.04.2012

Ако хардуерът има бутон за потребителя, прост трик е да преброите колко дълго е натиснат бутонът. С достатъчно бърз къс брояч получавате "случайно" число.

person Purple Tentacle    schedule 13.10.2009
comment
Знаете ли за някакви оценки на броя битове ентропия, като се има предвид скоростта на брояча от 'x' Hz? - person Craig McQueen; 01.11.2009
comment
Съжалявам, не. Предполагам, че някой умен може да го разбере. - person Purple Tentacle; 06.11.2009
comment
Това е добро решение, но в моя случай имам нужда от произволното число далеч преди да се осъществи взаимодействието с потребителя (всъщност, веднага щом micro получи мощност). Благодаря все пак за идеята. - person Donotalo; 07.01.2010

Генератори на псевдослучайни числа, които са най-бързите и най-малко взискателни с.р.т. наборът от инструкции (само shift и xor, без умножение или деление) са по-малки варианти на идеята на Mersenne twister (наречена генерализиран линеен регистър на преместване с обратна връзка). Самият Mersenne twister се нуждае от твърде много памет за микроконтролери.

Проблемът с тези генератори е, че те могат да генерират дълги последователности близо до нула, ако нямате късмет. При разумен размер на пространството на състоянието и инициализация от друг PNRG това обаче е малко вероятно.

Те също така не са сигурни за криптография или хазарт, интелигентен противник може да предвиди бъдещи състояния, след като наблюдава изхода. Това е така, защото те са линейни.

Веднъж проектирах такъв генератор за малък нестандартен процесор с пространство на състоянието от около 50 24-битови думи. Тествах варианти с пакета от тестове на Diehard, докато не намеря добър. Приложението генерираше случайни вариации за хардуерен тест.

person starblue    schedule 13.10.2009

Четенето на таймера и неговото xoring/nanding/и т.н. с поредица от битове ще даде полуслучайно на потребителя, тъй като времето между събитията вероятно ще бъде достатъчно раздалечено, така че потребителят наистина няма да може да каже корелацията с таймер.

person onaclov2000    schedule 06.01.2010

Ако можете да оставите щифт плаващ, това може да помогне за генериране на произволни числа с сместващ регистър с линейна обратна връзка. Не съм сигурен, че това е правилният начин, но моля, погледнете моя код:

// This code was written for 8051 (AT89S52)
unsigned char lfsr = 231; //8 bit shift register, with the seed of 231 or '11100111b'
unsigned char input_bit, i;

void main (void) 
{
    //Setup
    P0_0 = 0; // Leave Pin 0 Port 0 floating
    uart_init(); //Initializing uart/serial communication with pc


    while (1) 
    {
        for (i = 0; i < 255; i++) 
        {
            if (P0_0 == 1) // If Pin 0.0 is HIGH
            {
                input_bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1;
                lfsr = (lfsr >> 1) | (input_bit << 7);
            }
        }
        printf_tiny("%u\n", lfsr); //Send the random number to PC
        soft_delay(65535); //Simple delay function
    } //end while (1) loop

}

РЕДАКТИРАНЕ: Разбрах, че отговорът ми може да е лош. Повече подробности защо не трябва да използвате плаващ цифров щифт: https://electronics.stackexchange.com/questions/50476/random-number-generators-using-a-gpio-pin

person Hieu    schedule 16.11.2013