Користење на генератор на случаен број во Arduino: Случајни и RandomSeed функции. Arduino Course - Време и случаен Arduino генерира случајна секвенца на битови

При програмирање на Arduino, има моменти кога треба да добиете број кој нема однапред да му биде познат ниту на програмерот што ја пишува скицата ниту на корисникот кој ќе го користи Arduino со таква програма. Во овој случај, генератор на случаен (или поточно псевдо-случаен) број доаѓа на помош.



За да го активирате овој генератор, само користете ги функциите random() или randomSeed(). Овој материјал ќе ви покаже како да работите со овие функции, како и како да се ослободите од псевдо-случајноста при генерирање броеви.


Генерално, генератор на псевдослучајни броеви симулира хаотичен или случаен изглед на броевите, но всушност, ако анализирате серија од овие броеви во доволно долг период, можете да забележите одредена шема.


Значи, случајната функција за генерирање на псевдослучајни броеви може да има до два параметри и се запишува како случаен(max) или random(min, max). Овде, максималниот параметар, кој е задолжителен, ја поставува горната граница на опсегот за генерирање псевдослучајни броеви. Со користење на дополнителен параметар min можете да ја поставите долната граница на опсегот. Како резултат на тоа, функцијата ќе врати некој псевдо-случаен број во опсегот од min до max-1.


Важно е да се разбере дека кога се користи функцијата random(), секој пат ќе се генерира истата листа на псевдослучајни броеви. На пример, ако направите слот машина и првиот пат кога ќе ја притиснете рачката, таа покажува добитна комбинација, тогаш можете да бидете сигурни дека ако го ресетирате Arduino и повторно ја притиснете рачката, тој автомат ќе ја покаже истата добитна комбинација . Навистина, не е лесно да се имплементира машина за игри со целосно случајно генерирање броеви на Arduino, како што е, на пример, имплементирано во машините за игри www.igrovye-apparati-vulcan.com/, но делумно можете да го решите проблемот со помош на randomSeed () функција.


Оваа функција зема вредност (како цел број) и го користи бројот за да ја измени листата на случаен избор генерирана од функцијата random(). јамка. Но, дури и тогаш, фаќањето е дека иако низата на случајни броеви ќе биде различна кога се користи функцијата randomSeed(), таа сепак ќе биде иста секогаш кога ќе се изврши скицата.


Единственото решение во овој случај може да биде користење на аналогни периферни уреди (ADC) и соодветната функција analogRead(). Ако аналогниот влез не е поврзан со ништо, односно оставен „виси“ во воздухот, тогаш благодарение на бучавата на оваа линија можете да добиете навистина случајни броеви. Потоа во поставката за поставување можете да напишете randomSeed(analogRead(A0)). Под услов аналогната порта A0 да не е поврзана никаде.

Многу е напишано за генераторите на случаен број, но скоро секогаш кога станува збор за имплементација, се подразбира (или експлицитно наведено) дека ние зборуваме заза x86/x64 и други архитектури за „возрасни“. Во исто време, форумите посветени на развојот на уреди на микроконтролери се полни со прашања „како можам да генерирам случаен број на %controllername%?“ Покрај тоа, опсегот на одговори се протега од „погледни во Google/Wikipedia“ до „користете ја стандардната функција“. Оваа „стандардна функција“ не постои секогаш и одговара на развивачот во сите погледи; почесто е обратно: понекогаш бројките се далеку од случајни, понекогаш брзината на работа е премногу мала или понекогаш добиениот код не одговара во слободна меморија воопшто.
Ајде да се обидеме да откриеме кои се алгоритмите за генерирање на случаен број, како да го избереме вистинскиот и што е најважно, кои се карактеристиките на имплементацијата на овие алгоритми на контролорите.

Проценка на „случајноста“

Апликациите за RNG можат да бидат многу различни, од играчки до сериозна криптографија. Соодветно на тоа, барањата за генераторот исто така варираат во голема мера. Постојат специјални тестови за да се процени квалитетот (нивото на „случајност“) на генераторот. Еве ги најосновните од нив:
  • Тест за фреквенција. Се состои од броење на бројот на нули и единици во низа од битови. Треба да има приближно еднаков број на единици и нули.
  • Тестирајте за низа од идентични битови. Се пребаруваат редови со идентични битови, како 000...0 или 111...1. Распределбата на фреквенциите со кои се јавуваат сериите, во зависност од нивната должина, треба да одговара на оваа распределба за вистински случаен сигнал.
  • Спектрален тест. Дискретна Фуриеова трансформација се применува на оригиналната низа. Резултирачкиот спектар не треба да има значителни врвови што би укажале на присуство на периодични својства на низата.
  • Тест за автокорелација. Се пресметува корелационата вредност помеѓу копии од низа поместени релативно едни на други. Тестот ви овозможува да најдете региони кои се повторуваат во низа.
Постојат специјални комплети кои вклучуваат десетици слични тестови:
NIST - се користи во натпреварот AES за евалуација на алгоритми за шифрирање.
DIEHARD е еден од најригорозните комплети што постојат.

PRNG алгоритми

Секоја низа генерирана според строго дефиниран алгоритам не може да се смета за навистина случајна, затоа, кога се зборува за алгоритамски генератори, тие го користат терминот псевдослучајнопоследователна секвенца. Секој генератор на псевдо-случајни броеви (PRNG) ќе влезе во јамка порано или подоцна, другата работа е дека ова „доцна“ може да дојде за неколку милисекунди, или можеби за неколку години. Должината на циклусот зависи од големината на внатрешната состојба на генераторот N (всушност, ова е количината на меморија потребна на генераторот) и се движи од 2 (N/2) до 2 N бита.
Измислена е огромна разновидност на PRNG алгоритми, но не сите од нив се погодни за имплементација на микроконтролери. Ние сме строго ограничени во брзината и достапната меморија; многу контролери не поддржуваат реални аритметички или дури и инструкции за множење. Имајќи ги предвид овие ограничувања, ајде да погледнеме некои добро познати алгоритми.
Линеарен конгруентен метод
Следниот член на низата се пресметува со помош на формулата
X i+1 = (aX i + c) mod m
Број мго дефинира максималниот период на низата, цели броеви аИ в- „магични“ коефициенти. Број мРазумно е да се избере еднаква на моќност од два; во овој случај, операцијата за конверзија на модули е сведена на отфрлање на најзначајните битови. За да се добие максималниот период, мора да се исполнат следниве услови:
- ви m мора да биде релативно прост,
- а-1мора да биде повеќекратен стрза сите основни фактори стрброеви м,
- Ако ме множител на 4 (а во нашиот случај ќе биде множител), тогаш а-1мора да биде повеќекратно од 4.
Има уште една суптилност: само најзначајните битови од променливата на состојбата X треба да се земат како резултат, бидејќи за најниските битови статистичките параметри на случајноста се многу полоши. Линеарниот конгруентен алгоритам вообичаено се имплементира како стандарден rand() во многу библиотеки.

Добрите страни:

  • максималниот можен период за дадена големина на променливата состојба;
  • доволно брзо;
  • често веќе имплементирани во библиотеката на компајлерот.
Минуси:
  • потребна е операција за множење;
  • не се сите битови подеднакво случајни.
Резиме:брз и едноставен алгоритам за не многу тешки апликации.
Метод на Фибоначи со заостанувања
Овој алгоритам ја користи релацијата
X i = X i-a - X i-b,
каде е променливата состојба X- неозначен цел број. Вредности за одложување аИ бСе земаат не било какви, туку строго дефинирани, за да се постигне максимален квалитет, се препорачуваат парови (17,5), (55,24) или (97,33). Колку е поголемо доцнењето, толку е подолг периодот и подобри се спектралните својства на низата. Од друга страна, за да работи генераторот, потребно е да се складираат max(a,b) од претходните броеви, што не е секогаш прифатливо. Исто така, за да го стартувате генераторот потребни ви се макс(а,б) броеви, кои обично се добиваат со помош на поедноставен PRNG.

Добрите страни:

  • не бара операции за множење;
  • сите битови од случаен број се еквивалентни во статистичките својства.
Минуси:
  • бара голема количина на меморија;
  • бара голема низа на броеви за да се изврши.
Резиме:многу квалитетен, но интензивен алгоритам со ресурси.
Регистар за поместување на линеарна повратна информација


Променливата состојба е зачувана во регистар со должина N. Генерирањето на следната состојба вклучува два чекори:
  1. Вредноста на битот се пресметува C = X i1 xor X i2 xor… X ik, каде i1, i2…ik- повикани броеви на битови за регистрирање се наведнува.
  2. Регистарот е поместен за 1 бит надесно, најлевиот бит ја зема вредноста СО.
Излезот на генераторот е најдесниот (или најлевиот, или кој било) бит од регистарот, односно псевдослучајната секвенца се генерира по еден бит по повторување. Со правилно избрани броеви на допир, периодот на генераторот ќе биде 2 N - 1. „Минус еден“, бидејќи постои забранета нулта состојба на регистарот. Броеви на филијали за Нод 3 до 168 може да се најде во овој документ.
Покрај конфигурацијата опишана погоре, која, патем, се нарекува конфигурација на Фибоначи (да не се меша со истоимениот метод PRNG!), постои и т.н. Галоа конфигурација.


Наместо да го користи збирот на битови во секвенцата на допири за да генерира нов најлев бит, тој го XOR секој бит во низата на допири со најдесниот бит, а потоа го ротира целиот регистар надесно. Оваа шема е потешка за разбирање, но полесна за имплементација, бидејќи сите операции на XOR можат да се извршат истовремено. Во однос на должината на периодот и квалитетот на псевдослучајните броеви, шемите на Фибоначи и Галоа се еквивалентни.

Добрите страни:

  • многу едноставна имплементација, не бара ни аритметика, само операции со битови и поместувања;
  • многу брз алгоритам (особено шемата Галоа);
  • добри статистички својства.
Минуси:
  • треба да ја проверите почетната вредност за нееднаквост на нула.
Резиме:многу брз и прилично висококвалитетен алгоритам.
Криптоотпорни алгоритми
За употреба во криптографијата, PRNGs имаат уште еден суштински услов: неповратност. Сите алгоритми наведени погоре го немаат ова својство: знаејќи неколку излезни вредности на PRNG, можете, со решавање на едноставен систем на равенки, да ги најдете параметрите на алгоритмот (истите „магични“ константи а, б, витн). И знаејќи ги параметрите, можете да ја репродуцирате целата псевдо-случајна низа.
Секоја доволно силна блок-шифра може да се користи како криптографски силен PRNG алгоритам. Со избирање на таен клуч, можете да добиете блокови од псевдослучајни броеви со примена на алгоритмот на секвенцијални природни броеви. За N-битна блок шифра, периодот нема да биде повеќе од 2 N. Безбедноста на таквата шема целосно зависи од тајноста на клучот.
Сите модерни криптографски алгоритми се тестираат за употреба како PRNG, односно, користејќи сертифициран алгоритам, нема потреба посебно да се грижите за статистичките и спектралните својства на излезниот тек. Треба само да се грижите за пресметковната „лакомост“ на крипто алгоритмите. Ако треба да извршите голем број операции за шифрирање, има смисла да изберете контролер со хардверски криптографски блокови. Често ваквите контролери имаат и многу добар криптоотпорен хардвер PRNG.

Извори на ентропија

Како што веќе беше наведено, користејќи само детерминистички алгоритми, невозможно е да се генерира вистински случаен број. Затоа, обично се користи комбинација од PRNG + надворешни извор на ентропија. Изворот на ентропија се користи за поставување на почетната вредност за PRNG, а задачата на вториот е да обезбеди спектрална и статистичка чистота на низата. Што може да се користи како извор на ентропија? Да, речиси се.
Корисничка активност
Доколку уредот на кој било начин комуницира со корисникот, прилично добро решение би било да се користи самиот корисник како извор на ентропија. На пример, времето на притискање на копче, мерено со точност од една микросекунда (или подобро, неговите најмалку значајни цифри), е целосно непредвидливо. Меѓутоа, често уредот мора да работи автономно, што значи дека сме лишени од овој прекрасен канал на информации.
Аналогно-дигитален конвертор
Многу контролери имаат вградени ADC. И во многу контролори тие се со многу просечен квалитет, направени само „да бидат“. Битови со низок ред на резултатот ADC речиси секогаш содржат значителен шум, дури и при мерење на DC напон. Ова може да се користи: поврзете го влезот ADC со напонот за напојување преку делител, изведете неколку десетици мерења, земете ги најмалку значајните битови - тука имате одличен случаен број. Ако ADC содржи вграден предзасилувач, вклучете го, исто така е бучен.
Асинхрони генератори
Можете да ја користите разликата во периодите на два несинхронизирани генератори на часовници. Повеќето контролери содржат, на пример, тајмер за набљудување. За да се зголеми доверливоста, тој се тактира од посебен генератор, кој во никој случај не е поврзан со главниот сигнал на часовникот. Доволно е да се брои бројот на циклуси на главниот сигнал на часовникот во текот на еден период на тајмерот на чуварот. Ако изберете периоди така што бројачот се прелева многу пати за време на мерењето, можете да добиете прилично случаен број. Недостаток на овој метод е тоа што одзема многу време, до неколку секунди.
Часовник во реално време
Доколку дијаграмот има часовник во реално време, можете да ги користите нивните тековни читања за да го иницијализирате PRNG. На пример, со конвертирање на тековниот датум/време во формат на време Unix, веднаш добиваме 32 бита, што никогашнема да се повтори освен ако не читате повеќе од еднаш во секунда. Користењето реално време дава уникатност на вредностите, но не обезбедува никаква непредвидливост, па затоа е подобро да се комбинираат овој методсо други.
RC коло
Ако контролорот нема периферни уреди, покрај влезните/излезни порти, можете да го направите следново: едната нога е поврзана преку кондензатор со земјата, а преку отпорник на напонот за напојување. Ако влезовите на контролорот имаат внатрешни отпорници за повлекување, не е потребен надворешен отпорник.

Издаваме сигнал „0“ на оваа порта - кондензаторот е испразнет. Ја префрламе портата во режим на влез - кондензаторот почнува да се полни. Кога напонот преку него ќе го достигне прагот, влезот ќе се префрли од состојбата „0“ во „1“. Времето на полнење во голема мера зависи од многу фактори: напон на напојување, нанос на параметрите на RC колото, нестабилност на прагот, температура, протекување, пречки. Мерејќи го со доволна точност и земајќи ги најмалку значајните битови, можете да добиете добра случајност.
Хардверски генератор на бучава
За многу сериозни апликации (најзначајна криптографија), потребен е посигурен извор на ентропија од оние наведени погоре. Во такви случаи, тие користат дигитализација на сигналот од генератор на бучава врз основа на термички, ударни или дури и квантни ефекти. Елементот за бучава е обично специјална диода или зенер диода, сигналот од кој се засилува и се напојува до компаратор кој генерира бинарен поток на битови.

За да се осигура дека прагот на одговор на компараторот не влијае на статистичките својства на примениот сигнал, се користат два генератори на шум, кои работат на еден компаратор:

Заклучок

Конечно, ќе ви раскажам една приказна од мојот живот. Се започна со друго прашање поставено на форумот: „како можам да генерирам случаен број на контролорот? Авторот на прашањето објасни дека како проект на курсот прави уред кој имитира фрлање коцки. По неколку неуспешни обиди да се разберат алгоритмите, започнувачот на теми го сподели своето решение: тој едноставно навива вистинска матрица 1000 пати и ја наполни целата слободна меморија на контролорот со добиените броеви. Генераторот брилијантно ги помина сите тестови за „случајност“, имајќи предвид дека за време на демонстрацијата потроши помалку од една третина од својата „резерва“.
Затоа, таквото решение има и право на живот, особено ако се наметнуваат многу строги барања за случајноста на броевите, но тие не се бараат премногу често. Со драстично опаѓање на цените на меморијата, можеби е мудро да се опреми уред со „резерва за хаос“ што ќе трае цел животен век на уредот.
Ти благодарам за вниманието!

UPD1:Како што со право беше забележано во коментарите, доколку се очекува напад на RNG, а напаѓачот има хардверски пристап до уредот, надворешните извори на ентропија мора да се користат со голема претпазливост, бидејќи не е многу тешко да се замени сигналот од надворешен извор. Треба да се користат и внатрешни извори, покрај надворешните.
Исто така, добра идеја е да се акумулира ентропија сè слободно време, и користете го кога треба да генерирате друг случаен број. Обично во такви случаи т.н Ентропија базен- низа преку која периодично се извршува една од функциите PRNG и во која постојано се мешаат податоците од изворите на ентропија.

UPD2:Во многу случаи, корисно е да се зачува содржината на базенот Ентропија (извинете, не го знам нормалниот руски превод) во EEPROM, така што по исклучувањето и вклучувањето на уредот да не се акумулира повторно. Ова се однесува, пред сè, за добивање ентропија со помош на методот на асинхрони генератори: под доволно стабилни услови, истата низа може да се генерира по секое вклучување.
Ако се очекува напад, преземете мерки на претпазливост против манипулациите на EEPROM. Доколку контролорот го дозволува тоа, блокирајте читање/бришење/пишување со помош на битови за заклучување и кога го вклучувате, следете го интегритетот на EEPROM, барем користејќи едноставни контролни суми.

Тагови:

  • RNG
  • gpsch
  • микроконтролери
  • алгоритми
Додадете ознаки

случајно семе (семе)

Ја поставува вредноста, или семето, како почетна точка за функцијата random().

randomSeed(вредност); // поставува „вредност“ како почетна случајна вредност

Бидејќи Arduino не може да генерира вистински случајни броеви, randomSeed ви овозможува да ставите променлива, константа или друга функција во случајната функција, што помага да се генерираат повеќе случајни броеви.

„случајни“ броеви. Постојат многу различни семиња, или функции, кои можат да се користат во оваа функција, вклучително и millis(), па дури и analogRead() за читање на електричен шум преку аналоген пин.

случаен (макс)

случаен (мин., макс)

Случајната функција ви овозможува да вратите псевдо-случаен број во опсегот одреден со минималните и максималните вредности.

вредност = случаен (100, 200); // ја поставува „вредноста“ на случаен избор

// број помеѓу 100 и 200

Забелешка:Користете го ова откако ќе ја користите функцијата randomSeed(). Следниот пример создава случаен број помеѓу 0 и 255 и го прикажува PWM

сигнал до излезот PWM еднаков на случајна вредност:

int randNumber; // променлива за складирање на случајна вредност

int led = 10; // LED со отпорник на пин 10

void setup() () // поставувањето не е потребно

randomSeed(millis()); // поставува millis() со почетниот број

randNumber = случаен (255); // случаен број од 0 – 255 analogWrite (led, randNumber); // излез PWM сигнал

доцнење (500); // пауза за половина секунда

Извор: Гололобов В. – Од каде започнуваат роботите. За проектот Arduino за ученици (и не само) – 2011 година

Поврзани Мислења

Serial.begin (стапка) Ја отвора сериската порта и ја поставува брзината за сериски пренос на податоци. Типичната брзина на бауд за компјутерски комуникации е 9600, иако се поддржани други брзини. void setup() (Serial.begin…….

Сите променливи мора да се декларираат пред да се користат. Декларирањето на променлива значи дефинирање на типот на нејзината вредност: int, long, float итн., доделување единствено име на променливата и дополнително…….

Во ред, ја инсталиравме оваа програма. Го дебагиравме „механизмот“ на работа со модулот. И разгледавме неколку примери. Но, јас би сакал сам да создадам нешто корисно. Да пробаме. Прво, да го затвориме претходниот проект. За ова…….

Внимание! Кога работите со Arduino модулот во други развојни средини, треба да внимавате на конфигурацијата на микроконтролерот (Осигурувачи). Сè додека не знаете до што точно може да доведе промената…….

Време и случајност. Реакција

Овој пат ќе научиме кои се вредностите „Случајни“ и ќе научиме како да работиме со времето.

Ќе ни требаат:

  • Копче за такт
  • Скикер
  • Поврзувачки жици „МАШКО-МАШКО“

Реакција

Нашата задача за денес е да составиме дијаграм што ни овозможува да ја дознаеме брзината на нашата реакција.

Кога ќе го притиснете левото копче, се огласува сигнал по „случајно“ време. И кога ќе го притиснете десното копче, се забележува колку време поминало од чкрипењето до притискање на десното копче.

Вештите се обидуваат сами, а ние го гледаме дијаграмот.

#define BUZ 8 #define START 9 #define STOP 7 int time; //Променлива за синхронизација void setup() ( Serial. start (9600); pinMode (START, INPUT_PULLUP); pinMode (STOP, INPUT_PULLUP); pinMode (BUZ, OUTPUT); ) void loop() ( if(digitalRead (START) == 0) // Кога ќе го притиснете копчето СТАРТ.. ( int start_time = millis (); // Запомнете го времето на притискање = start_time; // Напишете го во глобална променлива. int Rand = случаен (0, 4000 ); // Ајде да генерираме „случајно“ време на одложување = време + Ранд; //Додај го доцнењето на времето (Ранд); //Почекајте тон (BUZ, 3000, 500); //Бип! ) if(digitalRead( STOP) == 0 && digitalRead( START) == 1) // Кога ќе го притиснете копчето STOP... ( int stop_time = millis (); // Запомнете го времето на запирање. време = stop_time - време; // Пресметајте го временска разлика. Serial.println("Време:"); // Изнесете го времето на Serial. Serial.println(time); delay(1000); ) ) // Пред вториот обид, повторно притиснете го копчето START.

Објаснувања

инт време; На променливите (не сите), при нивното означување, не мора да им се дава никаква вредност. Ја користевме оваа променлива за поврзување на две if искази.

Во C++, променливите декларирани во јамката нема да бидат достапни во другите циклуси, бидејќи тие имаат ефект само во тој циклус. Ова е направено за да се спречат програмски грешки. Кога ќе порасне програмскиот код, ќе разберете за што зборувам.

За да направите променлива достапна за повеќе изјави, треба да ја направите глобална. Оние. декларирајте променлива надвор од функциите.

millis ();Го враќа бројот на милисекунди кои поминале од стартувањето на програмата.

Ни треба за да го измериме времето што поминало од дадениот сигнал до копчето што се притиска.

случајно(мин,макс);Ова е генератор на случаен број. Зема две вредности. Генерира број во опсег од min до max.

„Случајни“ броеви бидејќи се специфична низа вредности. Многу долго, но исто. За да добиете различни секвенци, треба да користите СлучајноСемка();

Оваа функција го иницијализира генераторот. И ако го поставиме параметарот на случаен избор, тогаш ќе ги добиеме секвенците што ни се потребни. Редоследот ќе биде ист ако параметарот е фиксиран.

Заклучок

Сега можете да ја тренирате вашата реакција користејќи уред што сте го направиле сами. Или можете да продолжите да учите понатаму.

Список на радиоелементи

Означување Тип Деноминација Квантитет ЗабелешкаКупувајтеМојот бележник
Ардуино плоча

Arduino Uno

1 Во бележник
Даска за лебДаска за леб-пола1 Во бележник
Пиезо емитерПасивно1 Во бележник
Копче за тактБез брава2 Во бележник
Поврзување на жици„Папа-Тато“1



Врв