Нестабильность генерации, microsы и такты

   if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите 2 (10-й пин)
   else PORTB |= (1 << 2);          // установить 1 в бите 2 (10-й пин)

Как просто записать переменную в бит порта не нашёл.

Не помогло. Помог отказ от цифровой случайной последовательности. В одном полупериоде AnalogRead с потенциометра (на 24 микросекунды), в другом - AnalogRead наводок на А1. Всё симметрично, макс частота - 20 кГц, ну и пока ладно. Только нужны шумы, чтобы были наводки (кто-то должен стоять рядом и громко ругаться матом :slightly_smiling_face: ) Не хочу лепить дополнительный сдвиговый регистр :face_with_raised_eyebrow:

И да, вот это уже не так. Длительность nop’а зависит от типа переменной и ещё хрен знает от чего, так что и тут могут быть сюрпризы.

Если тебе по упражняться в программировании - за ради Бога.
Если нужно устройство (и заодно поупражняться в программировании), то я бы сделал иначе.

Взял бы AD9850 (например, вот тут: https://www.ozon.ru/product/tsifrovoy-generator-chastoty-ad9850-1550580482/ , но можно поискать и по дешевле).

AD9850 - это генератор сигналов от 1Гц до десятков мегагерц.

Даташит: https://static.chipdip.ru/lib/143/DOC000143901.pdf

Примеров использования на ардуино много в интернете.

Мне не нужен DDS генератор, нужно всего три цифровых выхода.

Можно и вообще без ардуины спаять на 5-7-и обычных микросхемах с обвязкой, а светодиодом мигать можно вообще на двух инверторах.

Без этого никак не получится? Может есть какой-нибудь быстро меняющийся разряд регистра, который можно было бы читать в цикле?

На таймерах попробуй сделать. На сколько я помню, там 62кГц вроде можно максимум. На 328-й три таймера. Калькулятор для таймеров есть в нете. В обработчике прерываний от таймеров на голом асме будет (push, sreg, in, xor, out, sreg, pop) 7 тактов + вход-выход из вектора. Или на голом таймере, вроде у AVR есть режим TOGGLE PIN, не помню. На трёх таймерах можно 6 сигналов генерить. Не помню, помоему на avrstudio можно классный компактный код генерить, там же и таймера посчитать. Давно на авр не шкодил)))

Да хоть на одном.

Базаришь… Я имел ввиду - БЫСТРО. )))

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

Почитай как устроен ПОРТ в контроллере. Можно прочитать БИТ, инвертировать его и записать обратно. ТРИ команды на асме. Это про авр. На кортексах асм гоОораздо “интереснее” , есть онлайн ресурсы, описания и тд.

Лучше бы даташит почитал, чем трындеть на форумах без устали.
PINx = 1<<bit //инверсия

  • для имитации “рандома”.

Если нужен однобитный рандом, самое простое и быстрое - на сдвиговых регистрах. Причем, возможна как аппаратная, так и программная реализация.

в одну строчку не знаю, на АВР по-моему никак.
В две примерно так же, как вы уже делаете:

PORTB &= ~(1 << 2);            // сбросить бит 2 (10-й пин)
PORTB |= ((RND & 1) << 2);    // записать RND в бит 2 (10-й пин)

где RND 1-битная переменная

Ну да, я от аппаратной как раз хотел уйти. Там 555-й таймер, сдвиговый регистр (LFSR), пара D-триггеров и логика. Здесь рандом - это типа “данные” для дальнейшей обработки в макете. От ардуины нужны 3 цифровых выхода. Пока вижу самое простое решение - добавить внешний шум, всё остальное работает нормально.

Да, RND - это “случайные” биты, который я теперь хочу нестандартно получить, чтобы не было дрожания фронтов.

Глубинный смысл этой фразы для меня темный лес, так что я в этой ветке обсуждаю только детали, в суть не вникаю.

Ну, если получать стандартно по функции random () или выводом из ранее заполненного массива, то импульсы на выходах нестабильные (фронты “гуляют” в пределах до 5 мкс)

из массива гулять не могут. Ищите ошибку в коде

С AnalogRead (A1) при наличии шумов всё работает нормально.

Вот так делаю, вроде нет ошибок:

 // unsigned int arr[32];  // массив случайных чисел
 // int i=0;
 // int j=0;

void loop() {

   // for(i = 0; i < 32; i++){ // в массиве будет 100 элементов 
   // arr[i] = random(65536);   // заполняем массив случайными числами 
   // }   

   noInterrupts();

   label:

   PORTB |= (1 << 1);               // фронт CLC (на первый выход)

    //RND = bitRead(arr[i], j);        // чтение битов массива

   if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите 2 (10-й пин) (на второй выход)
   else PORTB |= (1 << 2);          // установить 1 в бите 2 (10-й пин)

   if (RND < 1 && RND_OLD < 1) PORTB = PORTB^0b00001000;  // на третий выход

   // j=j+1;               //
   // if(j > 15) {         // последовательный перебор
   // j = 0;               // битов массива
   // i=i+1;               // (быстрее, чем random (2))
   // }                    //
   // if(i > 99) i = 0;    //

.
.
.
goto label и Interruprs в конце Loop'а

(часть кода)