Hạt giống nhỏ nhất và đơn giản nhất cho một trình tạo số ngẫu nhiên là gì?


40

Một bộ vi điều khiển nhỏ (8 bit Atmel) điều khiển một số đèn để trình chiếu một màn trình diễn ánh sáng với nhiều chuỗi ánh sáng ngẫu nhiên lạ mắt.

Một giả RNG phù hợp thực hiện công việc của nó một cách độc đáo, nhưng tôi đang tìm kiếm một hạt giống tốt cho nó. Một hạt giống sẽ là cần thiết bởi vì nếu ai đó bật nhiều thiết bị như vậy cùng một lúc, sẽ không tốt nếu tất cả chúng tạo ra các chuỗi hiệu ứng giống nhau cho đến khi chúng từ từ trôi đi do sự khác biệt nhỏ trong các nguồn đồng hồ riêng lẻ của chúng.

Một phương pháp rất tốt để tạo hạt giả RNG, mà tôi thường sử dụng, có thể trong trường hợp thiết bị phải được khởi động bằng cách nhấn nút hoặc lật công tắc. Ngay sau khi bật chế độ, có thể khởi động bộ hẹn giờ rất nhanh và giá trị của bộ hẹn giờ này sẽ tạo ra RNG ngay khi nhấn nút lần đầu tiên.

Vấn đề là, trong kịch bản này, không có nút nào. Chương trình phải bắt đầu ngay khi thiết bị được bật.

Vị trí trên PCB cực kỳ hạn chế (không có gì nhiều hơn một vài bộ phận SMD nhỏ nhất có thể phù hợp), vì vậy tôi đang tìm giải pháp nhỏ nhất và đơn giản nhất có thể. Do đó, tôi sẽ loại trừ các giải pháp ưa thích như phần cứng RNG thực, máy thu radio, v.v.

Tất cả những gì tôi có là bộ đếm thời gian 16 bit trong CPU và một chân cắm không sử dụng có quyền truy cập vào ADC.

Giải pháp hiện tại của tôi là chỉ sử dụng một điện trở (càng không chính xác càng tốt) để cung cấp khoảng một nửa điện áp cung cấp cho chân ADC và gieo RNG với giá trị chuyển đổi AD đầu tiên. Tuy nhiên, hiện nay hầu hết các điện trở 10% có độ chính xác dưới 1% (sẽ rất vui khi tưởng tượng ra khuôn mặt của một nhà cung cấp khi tôi nói với họ rằng chúng tôi muốn các điện trở SM chất lượng kém nhất mà họ có thể tìm thấy), vì vậy có khả năng rất cao nhiều đơn vị bắt đầu với cùng một hạt giống.

Một giải pháp thay thế tốt hơn sẽ là thực hiện nhiều chuyển đổi và xây dựng một giá trị từ các bit quan trọng nhất của các phép đo này. Tuy nhiên, tôi đã sử dụng bộ ADC loại này trước đây và tôi biết nó rất chính xác. Chạy ADC với tốc độ nhanh nhất có thể có ích ở đây.

Có ai có một đề nghị tốt hơn? Hạt giống không bắt buộc phải được phân phối đồng đều hoàn hảo, nhưng phân phối càng đồng đều thì càng tốt. Một hạt giống 16 bit với phân phối đồng đều hoàn hảo sẽ là một giấc mơ quá tốt là sự thật, nhưng tôi nghĩ rằng một phân phối nửa chừng trên 5 hoặc 6 bit có thể là đủ.


12
"sẽ rất vui khi tưởng tượng ra khuôn mặt của một nhà cung cấp khi tôi nói với họ rằng chúng tôi muốn các điện trở SM chất lượng kém nhất mà họ có thể tìm thấy" - sẽ còn vui hơn nữa khi để giá trị của điện trở này không được xác định trong sơ đồ mạch và nói với những người trong sản xuất rằng một phần này phải được hàn thủ công sau khi pcb ra khỏi máy định vị, ra khỏi thùng nơi chúng tôi trộn lẫn mọi giá trị điện trở mà chúng tôi có. - Bởi vì đó không phải là RNG mà tôi đang tìm, mà là một hạt giống . Vì vậy, nếu nó tạo ra cùng một giá trị gần như mỗi lần nó không tệ, thì điều quan trọng hơn là phải khác nhau giữa các thiết bị.
vsz

8
Tại sao không viết một giá trị ngẫu nhiên vào bộ lưu trữ EEPROM trong quá trình lập trình sản xuất? Bằng cách này, bạn có thể sử dụng RNG kỳ lạ nhất mà bạn thích vì nó sẽ chỉ có trong (các) lập trình viên sản xuất chứ không phải các thiết bị cuối. (Tín dụng cho @immibis: 'tệp phần mềm hơi khác' của bạn đã cho tôi ý tưởng.)
Calrion

2
Vì vậy, để rõ ràng% 100, vấn đề là họ có thể bắt đầu trên cùng một chuỗi, không phải là họ có thể trôi dạt theo thời gian, đúng không?
wedstrom

2
Sự lựa chọn các vấn đề RNG của bạn: một số cần hạt giống chất lượng tốt, một số khác thì không. Ví dụ, đối với Xorshift, bất kỳ hạt giống nào khác 0 sẽ hoạt động và sẽ hoạt động tốt như nhau. Ngay cả một sự khác biệt nhỏ trong hạt giống ban đầu sẽ dẫn đến một vị trí bắt đầu rất khác nhau trong chu kỳ của RNG.
tò mò

3
Bạn có thể kết hợp tất cả các câu trả lời ADC với số liệu thống kê và thời gian để có sự ngẫu nhiên hơn nữa. Ví dụ: đo xem cần bao nhiêu bộ xử lý cho đến khi bạn lấy N mẫu trong đó 3 LSB thấp hơn là 101 và mẫu M trong đó 3 LSB thấp hơn là 110. Mở rộng khái niệm này theo ý muốn.
wjl

Câu trả lời:


24

Đặt một điện trở song song và tụ điện giữa chân A / D và mặt đất. Làm cho điện trở khá cao, tốt nhất là cao hơn yêu cầu trở kháng tín hiệu đầu vào cho A / D. Làm cho thời gian RC không đổi có thể khoảng 10 trận. Ví dụ, 100 kΩ và 100 pF nghe có vẻ là một sự kết hợp tốt.

Để có được một giá trị với một số ngẫu nhiên, hãy lái pin cao trong một thời gian, sau đó đặt nó ở mức trở kháng cao và lấy A / D đọc một vài câu sau đó. Đặc biệt, nếu bạn lạm dụng đúng thời gian thu A / D, điện áp sẽ thấy sẽ phụ thuộc vào giá trị R và C, dòng rò của pin, tiếng ồn khác và nhiệt độ gần đó.

Lấy bit thấp hoặc hai bit thấp và lặp lại khi cần thiết để có được bất kỳ số bit ngẫu nhiên nào.

Đối với mẫu ngẫu nhiên hơn, thỉnh thoảng thực hiện quy trình này và đưa bit thấp của kết quả A / D vào trình tạo số ngẫu nhiên bạn đang sử dụng.


Nghe được đấy. Đảm bảo kiểm tra trở kháng đầu vào trên ADC - sê-ri Atmega8 có trở kháng đầu vào tương tự 100Meg khiến giá trị điện trở của Olin hơi thấp.
stefandz

3
@stef: Trở kháng đầu vào và trở kháng tín hiệu cần thiết để chuyển đổi chính xác là hai điều khác nhau. Có, trở kháng đầu vào rất cao do nó là CMOS. Tuy nhiên, có một giới hạn trở kháng tối đa trên tín hiệu để cho phép nó sạc mẫu và giữ nắp trong thời gian quy định và để khắc phục bất kỳ rò rỉ nào mà pin có thể có.
Olin Lathrop

2
xin lỗi, từ câu trả lời của bạn, tôi nghĩ rằng bạn đang tham chiếu trở kháng đầu vào trái ngược với thông số trở kháng nguồn. 10k là trở kháng nguồn tối đa được chỉ định của Atmega8, vì vậy câu trả lời của bạn là đúng chỗ. Để tham khảo, nắp S / H bên trong là 14pF, trong trường hợp bất kỳ ai cũng quan tâm.
stefandz

2
@stef: Tôi đã chỉnh sửa câu trả lời để làm cho điều này rõ ràng hơn.
Olin Lathrop

Bạn đã bỏ lỡ giai đoạn âm lịch và ngày lễ ngân hàng. Ngoài ra tay vẫy một bổ sung hữu ích, đặc biệt là nếu C thấp và không được bảo vệ tốt.
Russell McMahon

23

Một số tùy chọn có thể:

  1. Lập trình trước một địa chỉ nối tiếp duy nhất cho mỗi thiết bị. Nếu bạn có một thuật toán RNG đủ tốt, thì ngay cả một danh sách tuần tự các địa chỉ nối tiếp cũng sẽ tạo ra kết quả rất khác nhau.

  2. Tùy thuộc vào MCU / thiết lập của bạn, bạn có thể có hai nguồn đồng hồ khác nhau có sẵn cho đồng hồ hệ thống và đầu vào bộ đếm thời gian / bộ đếm thời gian theo dõi. Nếu một / cả hai có phương sai đáng kể, bạn có thể sử dụng điều này để tạo ra một hạt giống khác nhau phù hợp. Dưới đây là một ví dụ tôi đã viết sử dụng bộ đếm thời gian theo dõi nội bộ của Arduino và đồng hồ hệ thống XTAL bên ngoài .

  3. Sử dụng một bóng bán dẫn BJT và xây dựng một bộ khuếch đại phụ thuộc beta cao. Điều này có thể được đọc từ một ADC cho hạt giống.

  4. Các tụ điện / cuộn cảm thường được chỉ định cho một dung sai kém hơn nhiều so với điện trở. Bạn có thể xây dựng một số loại mạch lọc (RC, RL, LC) bằng các mạch này và đo đầu ra với ADC.


5
Tôi bỏ phiếu cho tùy chọn 1, đó là một giải pháp đếm phần không sẽ dẫn đến các chuỗi không bao giờ phải khớp. Số sê-ri và trình tạo RND có thể nói 16 bit làm cho bất kỳ thiết bị nào có cơ hội bắt chước mô hình của người khác không đáng kể.
KalleMP

1
Tôi cũng thích giải pháp một. Nếu bạn sử dụng thuật toán băm đơn giản, bạn sẽ ổn ngay cả khi bạn có số sê-ri liên tiếp.
magu_

6
Một điều thú vị về tùy chọn 1 là một số thiết bị đi kèm với số sê-ri tích hợp (thường là
micrô

3
Ngay cả một RNG rác như LCG cũng sẽ "tạo ra các kết quả cực kỳ khác nhau cho một danh sách tuần tự các địa chỉ nối tiếp" . Tôi cũng bình chọn cho 1.
BlueRaja - Daniel Pflughoeft

3
Nếu bạn có nguồn thời gian thì sử dụng nó làm cơ sở cho công tắc của bạn trên hạt giống sẽ giúp bù đắp mọi thứ giữa các lần chạy. Kết hợp điều này với một địa chỉ / số sê-ri hoặc địa chỉ MAC nếu thiết bị của bạn có một địa chỉ và bạn cũng sẽ sửa lỗi khớp giữa các thiết bị. Tôi đã thấy một số phần mềm lưu trữ liên tục một số hoặc mỗi số ngẫu nhiên được tạo để sử dụng làm hạt giống, ngay cả sau khi khởi động lại. Nếu thiết bị của bạn có thời gian hoạt động khác nhau, chúng sẽ trôi đi.
TafT

8

Bộ nhớ chưa được khởi tạo

Bạn có thể thử sử dụng bộ nhớ chưa khởi tạo trong bộ điều khiển vi mô. Mẹo nhỏ là tìm các bit có flip-flop 'cân bằng nhất và thực sự ngẫu nhiên. Quy trình là đọc tất cả bộ nhớ, thiết lập lại và lặp lại một vài lần để đo các bit nào thực sự ngẫu nhiên. Sau đó, bạn sử dụng bản đồ này để đọc đủ các bit ngẫu nhiên để gieo PRNG hoặc LFSR của bạn!

Phương pháp này sẽ cung cấp cho bạn các hạt ngẫu nhiên, ngay cả với phần cứng giống hệt nhau, nhiều chi tiết (và liên kết) có sẵn trong bài viết hack-a-day này

Tôi thích phương pháp này vì nó không yêu cầu bất kỳ mạch hoặc chân bổ sung nào; AVR của bạn đã có ram, bạn chỉ cần tìm các bit không ổn định (ngẫu nhiên). Ngoài ra thủ tục ánh xạ có thể được tự động; bạn có thể áp dụng cùng một mã và quy trình cho từng thiết bị và có kết quả thực sự ngẫu nhiên!


1
Bạn không thực sự cần phải tìm ra bit nào là ngẫu nhiên. XOR-ing tất cả các byte sẽ cung cấp cho bạn một kết quả ngẫu nhiên ngay cả khi chỉ 8 bit là ngẫu nhiên. Và như hình ảnh cho thấy, các giá trị thực tế có thể không ngẫu nhiên theo nghĩa tạm thời, chúng đủ độc đáo - đó chính xác là những gì chúng ta cần ở đây.
MSalters

1
Nếu bạn có thể tìm thấy một PRNG cho phép bạn "trộn" entropy, thì điều đó thậm chí còn tốt hơn tùy chọn XOR-then-seed. Lặp lại thông qua bộ nhớ chưa được khởi tạo và trộn các byte vào PRNG. Ví dụ, xem thư viện C chức năng trộn thư viện đơn giản của tôi .
Craig McQueen

Điều này sẽ không cung cấp cho bạn tính ngẫu nhiên chất lượng tiền điện tử.

@CamilStaps tất nhiên là không.
Navin

1
Điều này sẽ không hoạt động. Bộ nhớ chưa được khởi tạo là hành vi không xác định nếu tôi có một hệ điều hành và tôi không có quyền kiểm soát phần nào của bộ nhớ sẽ được gán cho chương trình của tôi và những gì đã có trước đó. Trên một vi điều khiển không có HĐH, đây không phải là trường hợp. Đặc biệt là với AVR, bởi vì tất cả RAM sẽ bằng 0 nếu đủ thời gian cho các tụ điện bị làm trống bởi mức tiêu thụ hiện tại trong màn hình tắt.
vsz

7

Những gì tôi đã làm cho một máy nghe nhạc MP3 có khả năng ngẫu nhiên là chỉ sử dụng một hạt giống tuần tự khác nhau ở mỗi lần bật nguồn. Tôi đã bắt đầu từ 1 và lưu trữ cái này trong EEPROM để ở chu kỳ năng lượng tiếp theo tôi sử dụng 2, v.v. Đây là trên ATMEGA168. Như hellowworld922 đã lưu ý ngay cả một hạt giống tuần tự đơn giản sẽ tạo ra các chuỗi giả ngẫu nhiên hoàn toàn khác nhau.

Tôi đã sử dụng một trong các trình tạo chuỗi ngẫu nhiên đồng dạng tuyến tính, điều này mang lại sự phân phối đồng đều.

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

Tất nhiên, nếu bạn muốn nhiều đơn vị có các chuỗi khác nhau mặc dù chúng có thể có cùng số chu kỳ công suất thì bạn cần một cái gì đó để bắt đầu ngẫu nhiên.

Điều này có thể được thực hiện bằng bất kỳ phương pháp nào được đề xuất bởi các áp phích khác - Một phương pháp tôi có thể nghĩ là có thể sử dụng đường chéo AC đi vào bộ xử lý nếu bạn có nó (ví dụ như điều khiển pha đèn)? Điều này có thể được sử dụng để lấy mẫu bộ đếm thời gian trên đường chéo đầu tiên sau khi bật nguồn và sau đó được sử dụng làm hạt giống.

Có bất kỳ nút ấn nào trên thiết bị để chọn chế độ không? Nếu vậy, bạn có thể lấy mẫu bộ đếm ngay lần đầu tiên nhấn nút sau khi MCU được lập trình, bạn có thể tạo một hạt giống ngẫu nhiên ban đầu và lưu trữ nó trong EEPROM. Mỗi lần khởi động sau thời điểm này sẽ sử dụng hạt giống được lưu trữ.


5

ADC là một nguồn rất tốt cho sự ngẫu nhiên.

Bạn không cần phải dựa vào dung sai điện trở. Bất kỳ điện trở nào cũng sẽ tạo ra nhiễu nhiệt và hiệu ứng vật lý tương tự sẽ đưa nhiễu vào ADC khi thực hiện tất cả các bước lấy mẫu và chuyển đổi. (Bảng dữ liệu sẽ cho bạn biết về mức độ nhiễu và cài đặt cấu hình nào tệ nhất / tốt nhất.)

Bạn không nên để chân ADC nổi; điều này có thể khiến điện áp trôi quá xa và có nguy cơ bão hòa đầu vào.
(Nhiều MCU cho phép bạn sử dụng thứ gì đó như một nửa điện áp cung cấp làm đầu vào ADC, để hiệu chuẩn. Điều này giúp tiết kiệm điện trở bên ngoài và vẫn gây nhiễu cho bạn.

Bạn không cần phải dựa vào một phép đo ADC duy nhất; bạn có thể kết hợp nhiều phép đo với hàm băm hoặc tổng kiểm tra đơn giản (CRC sẽ đủ). Nếu bạn cần bắt đầu sử dụng RNG ngay lập tức, sau này bạn có thể kết hợp kết quả ADC với hạt giống RNG hiện tại.


2
Tôi không chắc chắn tiếng ồn Johnson là phù hợp trong ứng dụng này; Tại STP, điện trở 10Meg trên băng thông 10kHz có 40uVnhiễu Johnson. Bạn sẽ cần một ADC> 14 bit hoặc một mạch khuếch đại để đo hợp lý điều này.
hellowworld922

STP không thực sự phù hợp. Nhiệt độ đặc biệt có thể được tăng lên một cách có chủ ý, nhưng thêm 60 độ so với STP chỉ là tiếng ồn thêm 10%.
MSalters

1
Một cách tiếp cận tương tự sẽ là sử dụng nhiễu bắn trong một diode. vi.wikipedia.org/wiki/Naty_generator#Shot_noir_generators
teambob

2

Bạn có thể lưu hạt giống từ phiên này sang phiên khác? Nếu vậy, có khả thi bật mọi đơn vị trong một khoảng thời gian ngẫu nhiên khi tạo không? Bằng cách đó, tất cả các đơn vị sẽ được vận chuyển với các hạt giống được cài đặt trước mà không giống nhau.

Một suy nghĩ khác: Làm thế nào để bạn liên kết nhiều đơn vị lại với nhau để chúng bật đồng thời? Nếu chúng nối tiếp, hãy thêm một số loại tụ điện để thiết bị (n + 1) bắt đầu một vài chu kỳ xung nhịp sau thiết bị thứ n. Lý tưởng nhất là các tụ điện sẽ phóng điện rất nhanh khi tắt thiết bị, vì vậy mỗi lần khởi động / khởi động lại có một khoảng cách lớn hơn giữa các chuỗi.

Nếu chúng song song, bạn vẫn có thể ngẫu nhiên hóa thời gian khởi động một chút. Tôi giả sử có một số loại lọc điện sử dụng tụ điện. Nếu vậy, việc chế tạo các thiết bị có các mạch lọc hơi khác nhau sẽ khiến mỗi thiết bị bắt đầu ở một thời điểm hơi khác nhau, gây ra sự phân kỳ sau vài lần khởi động lại.

Một biến thể của điều này là thêm phương sai cho tín hiệu đồng hồ của bạn nếu có thể. Chênh lệch 0,1% về tốc độ xung nhịp có thể có ít tác động đến màn hình ánh sáng, trong khi thay đổi tốc độ bạn đi qua bảng PRNG khá nhanh.


1
có lẽ kết nối một lượng lớn với tín hiệu tương tự trong pin và lấy một số bài đọc "mains hum" để tạo RNG.
Jasen

1
@Jasen, tất cả các đơn vị được kết nối với cùng một phần mở rộng sẽ thấy cùng một hum chính.
Ian Ringrose

2

Nếu bạn chạy trên nguồn đồng hồ "hiệu chỉnh" nội bộ. Bạn có thể không lưu hạt giống sau một thời gian, tốt hơn là vào EEPROM. Đồng hồ sẽ trôi, và nó sẽ khác nhau từ đơn vị này sang đơn vị khác. Để lưu lại giá trị mới sau một thời gian nữa (có thể sau mỗi 10 phút hoặc lâu hơn hoặc sau một khoảng thời gian đủ ngắn để xảy ra trong thời gian đúng giờ thông thường cho thiết bị. Thiết bị càng bật lâu thì càng có khả năng tiết kiệm một giá trị "khác biệt" vào EEPROM.

Ngoài ra, hãy thực hiện một bước nhảy một lần và sau đó (không thường xuyên) và khởi động lại khi thiết bị đang bật (lưu giá trị mới này trong EEPROM).


2

Điều gì về việc mở rộng ý tưởng ban đầu của bạn về chuyển đổi AD dựa trên một điện trở khác nhau bằng cách thêm LDR hoặc nhiệt điện trở? (Đầu tiên cần có khả năng "nhìn" bên ngoài, tôi không biết điều đó có khả thi hay không, nhưng sự thay đổi ánh sáng có thể cao hơn sự thay đổi nhiệt độ giữa các thiết bị bắt đầu cùng một lúc ở cùng một nơi. ..)


1
Thermistors đến với một tài sản hữu ích khác. Một số loạt từ hầu hết các nhà sản xuất có một phương sai rất lớn và không chính xác. Điều này sẽ tiếp tục "cải thiện" kết quả.
Ariser

1

2 giải pháp tiềm năng, cả hai đều cho rằng bạn cần một hạt giống duy nhất trên mỗi đơn vị.

  1. Nếu bạn flash từng đơn vị một trong nhà máy, tệp hex có thể được sửa đổi theo chương trình bởi một số tập lệnh trung gian trong lập trình viên. Nếu nó được điều khiển bằng máy tính, bạn có thể ghi đè một khởi tạo biến với ngày và giờ. Đảm bảo là duy nhất cho mỗi đơn vị!

  2. Các thiết bị dây Dallas 1 chỉ sử dụng một pin và mỗi pin đi kèm với một số sê-ri 64 bit duy nhất. Bạn có thể sử dụng nó như là hạt giống.


1
Tôi thích 2, nhưng tiếc là tất cả các bộ phận DS đều khá đắt.
Ariser

Đừng sử dụng dấu thời gian sản xuất cho tính ngẫu nhiên về chất lượng của tiền điện tử, điều này có thể dự đoán được.

2
@CamilStaps Đối với ứng dụng của OP, không yêu cầu chất lượng tiền điện tử
Hagen von Eitzen

1
@HagenvonEitzen đúng, nhưng những người khác có thể đi đến câu hỏi này để tìm kiếm sự ngẫu nhiên của tiền điện tử, vì vậy nó đáng được đề cập.

4
@CamilStaps Thở dài , có vẻ như bạn đã từ bỏ nhân loại :) Có thực sự quá đòi hỏi mong đợi từ một người muốn sử dụng câu trả lời từ thiết bị điện tử cho mục đích mật mã mà họ ít nhất đủ cẩn thận để đọc câu hỏi cần trả lời ? Hạt giống "16 bit" hoặc "5 o5 6 bit" không phải là tiền điện tử ngay cả khi được tạo ra bởi một nhóm mèo Schrödinger :)
Hagen von Eitzen

1

Bạn có thể để một chân ADC nổi để cung cấp cho bộ tạo số ngẫu nhiên (RNG) với nhiễu đã thu được. Nó là đủ để tạo ra một hạt giống hoặc thậm chí sử dụng nó như là trình tạo RNG.

Đừng quên sử dụng thời gian chuyển đổi tối thiểu có thể.

Giải pháp khác có thể là một bộ tạo tiếng ồn được áp dụng cho chân ADC.


2
Tôi sẽ thực hiện một số phép đo nhưng nếu tôi nhớ chính xác, một chân ADC nổi sẽ đọc 0hoặc gần 0. Tôi sẽ kiểm tra lại để xem nếu đó là trường hợp.
vsz

1
Tôi quan tâm, nó có đọc 0khi nổi không?
Bence Kaulics

2
Vấn đề là điều này có thể hoạt động trên một bảng phát triển và thất bại trong sản phẩm cuối cùng.
vsz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.