Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сгенерировать случайное число
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Страницы: 1, 2
DpInRock
Есть пикпроцессор. Внешних устройств - нет.
Требуется после старта программы сгенерировать случайный байт.
Старт программы осуществляется присоединением батарейки.
Число требуется ровно одно.

У двух одинаковых устройств после подсоединения батарейки должны генерироваться 2 разных числа.

Возможно ли такое? 07.gif
sergeeff
С точки зрения теории, всегда существует хоть и малая, вероятность, что числа будут одинаковыми.
Ден
Если имеется АЦП, то возможно произвести измерение "весящей" в воздухе ноги и взять младший бит. И таким образом добрать до нужного количества бит.
DpInRock
У меня нет висящих ног. Но хотелось бы решить хитростью какой-нибудь. Там все очень стабильно (питание от батарейки). И АЦП даст слишком малую разницу.

У меня впечатление, что это невозможно. Поэтому и обратился к мировому сообществу. Все синхронно. Была надежда что запись в память EPROM случайна по времени - но нет. Как-то одинаково все.
Okorok
Цитата(DpInRock @ Aug 12 2008, 13:10) *
Есть пикпроцессор. Внешних устройств - нет.
Требуется после старта программы сгенерировать случайный байт.
Старт программы осуществляется присоединением батарейки.
Число требуется ровно одно.

У двух одинаковых устройств после подсоединения батарейки должны генерироваться 2 разных числа.

Возможно ли такое? 07.gif
Не забывайте: Разных байтов бывает всего лишь 256.
Т.е. вероятность совпадения "случайных" чисел у двух разных устройств будет минимум 1/256.
DpInRock
Разумеется. Мне достаточно будет если ДВА разных устройства выдадут просто разные числа. Скажем от 1 до 10.
Т.е. подсоединяем батарейку у двух устройств. А они с вероятностью хотя бы 50% выдают разные числа. (Хотелось бы вероятность побольше, но на худой конец хватит и такой).

Поясню.
При первом подключении батарейки устройство должно сгенерировать свой адрес - 1 байт. И все.
При этом другое устройство (с понятной вероятностью) должно сгенерировать другой байт.
Flasher
а слабо еще серийник присвоить и завести его в механизм генерации. Плюс еще в епром писать для следующей генерации.
DpInRock
Слабо.

Надеюсь, что это на самом деле невозможно без внешнего источника случайного события.
Voice2001
Вы бы дали информации побольше о своем устройстве. Возможно получилось бы откуда-нть достать это число
Цитата(DpInRock @ Aug 12 2008, 15:31) *
Поясню.
При первом подключении батарейки устройство должно сгенерировать свой адрес - 1 байт.

нужен адрес устройства? может тогда задержать их во времени и по порядку присваивать адреса (ессно между собой их придется связать)
гадать можно долго. Подробней расскажите
DpInRock
Эти устройства никак не связаны друг с другом. Лежат себе на складе, никого не трогают.
Приходит человек, берет устройство и уходит. Вставляет батарейку. Бабах - устройство придумало себе адрес.

Потом, через год, этот человек берет другое устройство. Приходит к себе домой, вставляет батарейку - бабах - устройство придумало себе адрес. И с тем устройством, что уже у него имеется - не совпадает (с учетом вероятности).
Dr.NoA
Цитата(DpInRock @ Aug 12 2008, 15:24) *
У меня нет висящих ног. Но хотелось бы решить хитростью какой-нибудь. Там все очень стабильно (питание от батарейки). И АЦП даст слишком малую разницу.

Так есть АЦП или нет? Даже если его вход не висит в воздухе, все равно младший разряд скакать будет, поэтому делаете n измерений, в каждом из которых берете младший разряд, и их них составляете n-битное случайное число.
MrYuran
Идея такая.
На входе АЦП RC-цепочка, соединённая с питанием. При включении засекаем время и мерим напряжение.
Младший байт, я думаю, будет достаточно случайным.
Ещё есть алгоритмы псевдослучайных последовательностей, можно использовать измеренное напряжение с АЦП для инициализации ПСП
MMos
Действительно, мало информации. Мои соображения: если не писать ничего уникального внутри контроллера и ничего не цеплять снаружи, то гарантировать случайность невозможно. Однако, автор вопроса лукавит. Ведь если устройство никуда не подключается, то зачем ему адрес?
kurtis
Можно попробовать вычитывать содержимое ОЗУ перед инициализацией, теоретически оно будет случайно.
А часы реального времени присутствуют???Если да, то тогда при условии что устройства не будут включатся одновременно, то можно просто складывать месяц + день + часы + минуты + секунды или что-то вроде того
DpInRock
Спасибо за идею составлять число из младшего бита АЦП.
То, что нужно.

Добавлю к нему считывание посередине преобразования. СПАСИБО.
(Хотя, нет. не добавлю).
rv3dll(lex)
1 на ацп завести напряжение батареи, через делитель из неточных резисторов немаркированных, которые будут ставить как попало.

разобраться с контроллером с его битовым файлом на загрузку и отвести там область, в которую писать ключ текущее время например - просто файл прошивки надо обработать программой перед каждой прошивкой.
Amper25
Можно сделать гораздо проще, без всяких АЦП и пр.

При первом подключении батарейки, запустить программный 8-бит счетчик и инкрементировать его по возможности с наибольшей частотой. Одновременно записывать его значение в ячейку(или поочередно в 2 ячейки) EEPROM. Потом выдернуть батарею и опять вставить.
Если время записи в EEPROM составляет 5-8мс, то если разница во временах удержания батареи разных устройств больше 5-8мс(что логично) то и "RANDOM" числа будут отличатся.

Единственное что можно добавить, лучше писать в 2 ячейки поочередно, и если питание обрывается на процессе стирания ячейки, то хотябы в одной из них будет число отличное от 0xFF.
Ну и само значение 0xFF надо считать не RANDOMOM.
DpInRock
Попробую. Хотя думаю, что запись в епром синхронная.
А АЦП стоит как вкопаный гад. Вот когда не надо, дергается. А тут железно меряет. Даже удивительно. И младший разряд стоит.

А может можно программатор научить ячейку образа памяти инкрементировать?
Точно. Просто напишу программку, которая раз в секунду увеличивает содержимое ячейки в нужном месте хексфайла. Правда, там еще надо будет контрольную сумму фиксить...
А программатор всегда проверяет файл на свежесть (ПикКит2).

Вот самый удобный наверное способ. Спасибо всем за участие.
Как оказывается ен просто не на IBM число сгенерить.
one_man_show
Может быть ошибаюсь, давно не работал с пИками, но вроде была раньше какая-то возможность программировать область памяти так, чтобы получить неустойчивое значение, тогда достаточно при запуске читать известные ячейки памяти программ
DpInRock
Да сложно все получается, если программно решать вопрос.
Дело копеечное.
Все-таки правильнее сделать процесс управляемым. Т.е. снаружи писать прогу, которая правит хекс. По крайней мере надежно и точно. И числа будут точно не совпадать.
DpInRock
Может кому пригодится.
Опробованы все способы.

Самым надежным и приятным в реализации оказался озвученный тут совет суммирования памяти.

Тесты показали, что память инициализируется действительно случайными числами. Даже не FF 00 F0 0F. А нормальными такими числами. Там, 18, 75, 36....

Полсотни раз порпобовал - числа не повторились. Хотя могли бы.

А реализация - всего одна строка.

Рад в усмерть. Спасибо еще раз.
Amper25
Цитата
Рад в усмерть. Спасибо еще раз.


Не стоит устраивать преждевременных празднований. С Пиками много не работал, не могу сказать. Но на AVR с tiny26 были случаи когда в L(Low voltage) версии память инициализировалась случайными числами, а в обычной версии контроллера - сплошными нулями.

Вообщем, может полуцчится так, что на некоторых версиях это не сработает.
kurtis
Возможно вы использовали разные версии компилятора. Т.к. обнуление ОЗУ это задача программы, и например в WinAVR процедуры "обнуления" ОЗУ находятся в модуле crtxxxx.o, и можно увидеть как в начале программы, еще перед вызовом main(), выполняется код, который обнуляет секцию bss (т.е. ОЗУ)
Amper25
Для tiny26 я писал на ASM, и никаких процедур обнуления там не было.
DpInRock
Я делаю все из МСС18. Не стал вмешиваться в стартапные вещи (еще чего, нам, боярам не с руки ковыряться). У компилятора действительно есть неинициализируемые области, которые он явно указывает.
Но так как я суммирую вообще ВСЮ память, то все нормально получится.
На самый худой конец (самый худой) - последствия не очень фатальны. Это не прицел баллистической ракеты.

Действительно, почему я не стал в первую очередь ориетироваться на память, ибо опыт работы с осталными процами говорил, что память чаще всего именно обнуляется аппаратно (в смысле, сама по себе). ....
Rst7
На память я бы полагаться не стал. А вот использовать тот факт, что тактовая частота WDT и тактовая самого проца - суть разные генераторы, вполне можно. Для этого достаточно запустить TMR0 по сбросу от PowerUp и по сбросу от WDT взять несколько младших битов TMR0. При необходимости повторить до получения нужного количества бит. Кстати, какой основной генератор используется, внутренний RC, внешний RC или кварц?
DpInRock
Внутренний.
Не хотелось бы строить еще один автомат. Хотя так можно, конечно.
Огурцов
Цитата(DpInRock @ Aug 12 2008, 11:10) *
Требуется после старта программы сгенерировать случайный байт.

Нужны стабилитрон, в качестве генератора шума, резистор и АЦП на борту, желательно с усилителем.
Я использовал дифференциальный и дополнительно RC цепочку для выделения постоянной составляющей, для подключения второго входа.
DpInRock
Как вообще генерировать случайные числа я себе представляю.
Как генерировать их без внешних устройств - вот в этом вопрос.
DeadMoroz
Соглашусь с Amper25:
"Можно сделать гораздо проще, без всяких АЦП и пр.

При первом подключении батарейки, запустить программный 8-бит счетчик и инкрементировать его по возможности с наибольшей частотой. Одновременно записывать его значение в ячейку(или поочередно в 2 ячейки) EEPROM. Потом выдернуть батарею и опять вставить.
Если время записи в EEPROM составляет 5-8мс, то если разница во временах удержания батареи разных устройств больше 5-8мс(что логично) то и "RANDOM" числа будут отличатся.

Единственное что можно добавить, лучше писать в 2 ячейки поочередно, и если питание обрывается на процессе стирания ячейки, то хотябы в одной из них будет число отличное от 0xFF.
Ну и само значение 0xFF надо считать не RANDOMOM."

Если есть кнопка или свободный вход, то можно поступить так: перед включением устройства нажимаем кнопку/устанавливаем вход в нужный уровень и после включения питания в процессе инициализации проверяем ее состояние - если активно, то инкриментируем 1/2 байта, далее, после того как пользователь отпустит кнопку/деактивирует вход, считываем текущее значение переменной. Проверено - работает.
DpInRock
Идея с Eprom мне не нра по одной причине. Бывали случаи ( в практике), когда портилось не только то куда пишешь. Т.е. снятие питания во время записи в общем случае чревато траблами в других местах.

С кнопками - да. Но на устройстве нет ни одного элемента индикации. Очень неприятно давить кнопки наугад. Тем более - неспециалисту.
rx3apf
Цитата(DpInRock @ Aug 13 2008, 03:41) *
Идея с Eprom мне не нра по одной причине. Бывали случаи ( в практике), когда портилось не только то куда пишешь. Т.е. снятие питания во время записи в общем случае чревато траблами в других местах.

Я на 100% уверен, что время записи байта в EEPROM не может совпадать у разных экземпляров с точностью до такта процессора (точнее, дискретность будет равна времени цикла опроса флага завершения). А время записи (единицы mS) достаточно велико, чтобы прокрутить цикл по крайней мере пару сотен раз при разумной тактовой частоте...
domowoj
Цитата(DpInRock @ Aug 13 2008, 03:39) *
Как вообще генерировать случайные числа я себе представляю.
Как генерировать их без внешних устройств - вот в этом вопрос.

А поиском в инете пользовался?
Встречал генерирование как случайных так и псевдослучайных чисел,
если интересно, вечером дам ссылки.
DpInRock
Согласен, что задержка для флэшки не должна зависить от тактовой процессора. По идее.
Ledmaster
Конечно, обсуждаемая тема имеет некий общеобразовательный смысл, но такое решение очень ненадежно, поскольку велика вероятность совпадения "случайных" чисел, сгенерированных по одному и тому же алгоритму на почти идентичном "железе".
Вы же не собираетесь производить Ваш девайс миллионами экземпляров, так почему бы просто не прошить в каждый, намертво, уникальный (в рамках предполагаемог количества экземпляров) серийный номер? За всех не поручусь, но возможность автоматического инкрементального присвоения серийного номера достаточно часто встречающаяся в средах разработки функция (обычно находится во вкладке флэш лоадера).
DpInRock
Решение достаточно. Ибо случайные числа любого диапазона имеют право совпадать. Даже самые настоящие случайные числа.
Посему - все нормально.
Когда не хотят, чтобы что-то совпадало, как например MAC адреса сетевых карт, то не используют случайные числа.

Мое устройство просто в радиусе своего действия - 50 метров, не должно сталкиваться по адресам с другим устройством. И все.
А устройств в одном радиусе действия ожидается не больше двух трех. Поэтому 65536 адресов - вполне достаточно. За глаза. (Где генерируется одно случайное число, там генерируется и второе - задача эквивалентная).
rv3dll(lex)
Цитата(DpInRock @ Aug 13 2008, 14:48) *
Мое устройство просто в радиусе своего действия - 50 метров, не должно сталкиваться по адресам с другим устройством.


когда микрочип разрабатывал свой модуль шифрования сигналов автосигнализаций он не надеясь на случайность и количество сделал их все разными
алгоритм шифрования там достаточен чтобы поменять батарейку и после этого не ломать дверь.
как будете разруливать ситуацию разряда батареи???
_Ivan_33
простите что вмешиваюсь ...
#include <stdlib.h>
и использовать rand();
при этом указать rand_max
rx3apf
Цитата(_Ivan_33 @ Aug 13 2008, 15:37) *
простите что вмешиваюсь ...
#include <stdlib.h>
и использовать rand();
при этом указать rand_max

"Шутку понял. Смешно" ©
Ну и какие результаты будут при выполнении на одинаковых кристаллах с одинаковой растактовкой и одинаковыми исходными данными ? Очень-очень условно можно _предполагать_ случайное состояние ячеек оперативной памяти, но не более того. Без привлечения дополнительных аппаратных средств можно полагаться либо на время записи в EEPROM данных (у PIC16 - можно, у MSP430 - нельзя), либо на разные тактовые частоты опорного генератора и RC-тактируемого WDT (как уже было предложено). Других вариантов я, например, вообще не представляю...
xemul
Запустить таймер, дождаться сброса по собаке, прочитать таймер. А с прескейлером, назначенным на таймер собаки, даже 16-битный таймер успеет несколько раз переполниться.
В новых пиках точность таймера собаки подняли, поэтому стОит или перемешивать биты, или пропустить считанное значение через CRC-образный алгоритм.
DpInRock
Цитата(rv3dll(lex) @ Aug 13 2008, 15:28) *
когда микрочип разрабатывал свой модуль шифрования сигналов автосигнализаций он не надеясь на случайность и количество сделал их все разными
алгоритм шифрования там достаточен чтобы поменять батарейку и после этого не ломать дверь.
как будете разруливать ситуацию разряда батареи???

Адрес генерируется раз в жизни. И пишется во флэшку.
Устройство крайне маленькое, потреблять должно не более 5 микроампер (в среднем).

Достаточно сделать генерацию нового адреса по подсоединению батарейки, как все проблемы с совпадениями снимаются. Если совпало - просто переткни батарейку еще раз.

Но я так не сделал. Ибо на пиковый случай, когда в одном месте собираются очень много устройств (сложная система), то там присутсвует управление устройством через RS232? где ты можешь в ручную задать все параметры.

А для простых случаев - сойдет и так.

Это устройство - просто радиокнопка на 10 выключателей. Типа умный дом и все такое.
Просто встала задача при массовом тираже (всего 1000 шт. в год) упростить задачу записи разных адресов по умолчанию.
rx3apf
Цитата(DpInRock @ Aug 13 2008, 17:35) *
А для простых случаев - сойдет и так.

Это устройство - просто радиокнопка на 10 выключателей. Типа умный дом и все такое.
Просто встала задача при массовом тираже (всего 1000 шт. в год) упростить задачу записи разных адресов по умолчанию.

И все же я бы подумал и о дополнительном "аппаратном" решении. В виде хоть какого джампера/кнопки на плате, выполняющего начальный сброс устройства. Т.е. при установке батареи хоть каким из предложенных способов генерируем некоторое "суррогатное" "случайное" число, а потом в течении какого-то разумного времени пользователь должен сделать сброс. А вот в течении этого времени до сброса крутить счетчик с максимальной скоростью. Момент сброса будет вполне случайным и результат (сохраняемый в оперативной памяти) - тоже. Ну, а если все ж сброса не было, то по истечении таймаута (а то цикл сожрет много электропитания) будет то, что сгенерировалось в момент включения. В конце концов, возможность аппаратного сброса есть практически везде и повсеместно, начиная от наручных часов...

Стоп-стоп... Радиокнопка, говорите ? Т.е. кнопка уже есть ? Ну так от включения и до первого нажатия на кнопку можно медленно и печально, не особо расходуя питание, крутить какой-нибудь таймер. И по нажатию на кнопку сохранить полученный результат, который и будет требуемым "случайным числом". Или я чего-то в логике работы недопонял ?
xelax
Ставте DS2411 и не мучайтесь ненужными проблемами. Кнопки, еепром, ацп, память и прочее... wacko.gif
zltigo
А слабо внимательно перечитать пост Rst7? И не заниматся народным творчеством?
Ledmaster
Цитата(xelax @ Aug 13 2008, 19:56) *
Ставте DS2411 и не мучайтесь ненужными проблемами. Кнопки, еепром, ацп, память и прочее... wacko.gif

Да, дополнительные пару долларов себестоимости, это как раз то, что нужно для радиобрелка! smile.gif

А все таки, как насчет банальной сериализации? В конце концов, можно успокоится на внешней проге, которая непосредственно в .hex файл будет прописывать серийный номер и править CRC (если нужно) перед каждой прошивкой.
DpInRock
Хотел успокоится на внешней проге с самого начала. Но потом прикинул, что это мне ее писать...
И что-то расхотелось. Заказчик лишней работы не оплатит.
rv3dll(lex)
Цитата(DpInRock @ Aug 13 2008, 17:35) *
Адрес генерируется раз в жизни. И пишется во флэшку.


значит я не угадал применения
1 раз ломать дверь машины пришлось - разбивать стекло (((
DpInRock
А ключем?
@Ark
Цитата(rx3apf @ Aug 13 2008, 17:53) *
... Радиокнопка, говорите ? Т.е. кнопка уже есть ? Ну так от включения и до первого нажатия на кнопку можно медленно и печально, не особо расходуя питание, крутить какой-нибудь таймер. И по нажатию на кнопку сохранить полученный результат, который и будет требуемым "случайным числом". Или я чего-то в логике работы недопонял ?

Вот это, с моей точки зрения, наиболее правильное решение! Кстати, не раз мною использованное...
В качестве источника случайного числа нужно использовать действия пользователя, а точнее - временной интервал между двумя любыми его действиями. В качестве старта логично использовать первое включение питания (подсоединение батареи). Далее - запускается 8 или 16 разрядный таймер, который останавливается (фиксируется) при обнаружении второго действия пользователя. Полученное значение записывается в EEPROM...
Что именно использовать для остановки таймера - решать разработчику. Вариантов масса - первое нажатие кнопки, перемещение движка резистора (если, конечно, они есть), первое обращение к устройству со стороны других устройств и так далее... Как правило, всегда можно найти источник...
Этот метод дает действительно случайные значения. Кроме того, он прост и надежен. Не усложняет устройство и не требует дополнительных манипуляций при изготовлении и использовании устройства...
rv3dll(lex)
Цитата(DpInRock @ Aug 14 2008, 00:43) *
А ключем?


через несколько лет эксплуатации без использования личинок они захрясают настолько, что их можно разве что высверлить.

к тому-же личинки ключей - возможность открыть ножницами
их при установке актуаторов часто отключают

Цитата(@Ark @ Aug 14 2008, 03:38) *
Этот метод дает действительно случайные значения. Кроме того, он прост и надежен. Не усложняет устройство и не требует дополнительных манипуляций при изготовлении и использовании устройства...


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

вот на этом этапе и надо присвоить номер - 1 раз и навсегда

на плате предусмотреть поле для корочения - ту самую кнопку
можно поставить даже скрытую кнопку (нажимать булавкой) и сделать это фичей

подключили плату к источнику - нажали кнопочку - состояние таймера записалось во флеш
проверили надели корпус и положили на склад.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.