LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: almamater em 28 de Novembro de 2020, 00:12
-
Alguém que tem alguma forma de gerar números aleatórios mas mesmo aleatórios?
Não precisava de algo muito mega eficiente mas é que a forma 'normal (https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/)' que existe no Arduino para Random Generator não é lá muito aleatório.
Andei a pesquisar e há N discussões sobre isto e cheguei a esta biblioteca: Entropy library (https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library), que até acho que funciona muito bem mas ao mesmo tempo é algo muito elaborado parece-me para o que quero..
Simplesmente entre os números X e Y quero obter um número mas que não se esteja sempre a repetir que nem parece aleatório.
Com o método 'normal' do randomSeed(analogRead(0)) há forma de melhorar o resultado? Provocar mais ruído no pino usado?
-
Alguém que tem alguma forma de gerar números aleatórios mas mesmo aleatórios?
a forma 'normal' que existe no Arduino para Random Generator não é lá muito aleatório.
Em que te baseias que nao e' suficientemente aleatorio para ti?
Sera um pseudo random generator, que deverá ter uma repetição do padrão. Qual é essa frequencia dessa repetição?
Depois de saberes, podes procurar outros altoritmos pseudo-aleatorios e escolher um que tenha uma repeticao mais longa.
Os MCUs mais recentes trazem um módulo analógico para gerar entropia / valores aleatorios..
de resto, por software, só é possivel pseudo-aleatoriedade.
-
Fizeste-me lembrar a "plotter" que levei à makerfaire em 2014. Tem um botão que dá inicio ao desenho de um perfil de cidade. Cada perfil é gerado com elementos aleatórios e é único (bom, na verdade é um dos 65536 perfis possíveis :D). Para obter essa aleatoriedade e ligá-la à pessoa que carrega no botão, tenho um contador (16 bits) que incrementa constantemente em wraparound à "velocidade do CPU" e pára quando a pessoa carrega no botão. Depois uso o valor desse contador como semente para o gerador de números aleatórios. Isto corre num ATTiny46. Não sei quão bom é o gerador de números aleatórios mas cá fica na mesma; pelo código que tenho comentado no projecto, foi uma preocupação minha e fiz um teste para ver o aspecto da coisa. Acho que na altura pesquisei e encontrei esse algoritmo em algum lado. Seguem-se excertos do código.
typedef uint16_t word;
typedef uint8_t byte;
static word gRand = 89;
static byte rand (void)
{
static const byte EEMEM sSeeds[8] = {5, 23, 51, 89, 43, 11, 7, 7};
static byte sIdx = 5;
sIdx = (sIdx + gRand + 3) & 0x07;
gRand = gRand * 109 + eeprom_read_byte((byte*)(&sSeeds + sIdx));
return gRand & 0xff;
}
// Pick a random number from 0 to (n-1) (one number from a set of n).
static byte Rand (byte n)
{
return ((word)n) * rand() / 255;
}
(...)
static void WaitKey (void)
{
word ctr = gRand;
while (PINB & _BV(ePinDRLL)) ctr++;
gRand = ctr;
}
// main() ...
/*/ Quick check of the randomness of our rand function
{
byte a;
for (a = 0; a < 100; a++)
{
sendch(Rand(2) + '0'); // 0 or 1
USendEEStr("\r\n");
}
USendEEStr("--\r\n");
for (a = 0; a < 100; a++)
{
sendch(Rand(10) + '0'); // 0 to 9
USendEEStr("\r\n");
}
}*/
-
Existem várias formas de se gerar números aleatórios:
- Pseudo aleatório (funciona bem quando vai buscar o timer do micro ou de um rtc)
- Intervenção humana (vai buscar um nº do incrementador ao ser pressionado um botão)
Este último é 100% aleatório e coloquei esse processo quando desenvolvi o jogo "simon" ou "tetris"
Parece que o Njay também usou um parecido ::)
Em programação no pc, para se gerar um nº executa-se randomize, que vai registar o inicio dos nºs de acordo com o timer, ao se chamar o comando random, este será uma série em pseudo (através de um calculo interno).
-
:)
Quando digo que a função que referi não é 'suficientemente aleatoria' é porque, para além de existirem mais pessoas a dizer o mesmo, implementei a mesma há uns anos num Attiny para que sejam gerados nºs aleatórios até 30 (se não me falha a memória) e por forma a que seja depois escolhido o ficheiro MP3 correspondente.. acontece que há músicas que estão constantemente a tocar e outras não, mesmo sendo aleatório parece que há um padrão e os mesmos números acabam sempre por sair.
Logicamente não tenho nada muito em concreto para defender esta minha teoria, a não ser o que li sobre isto e de facto na prática com o 'projecto' que fiz há uns anos e que ainfa hoje tem o mesmo comportamento :)
-
Ahh, mas se a aplicação é essa, o que tu queres fazer é arranjar uma playlist "baralhada". Aí tens a garantia que todas as músicas vão ser tocadas durante uma passagem pela playlist. Copias a playlist ou a lista de músicas para uma lista à parte, a lista "aleatória". Mas em vez de percorreres a lista inicial de uma ponta à outra, escolhes um elemento ao calhas e copia-lo para a lista random. Depois tiras esse elemento da lista original, ficando apenas os elementos que ainda não foram escolhidos. E continuas a fazer isso até que ficas com a lista original vazia. No final tens uma lista random em que todas as músicas são tocadas exactamente uma vez. Tás a ver o algoritmo?
Há outras formas de fazer, mas o essencial é que ficas com uma lista que tem à mesma todas as músicas mas por uma ordem aleatória.
-
:) estou a ver e é uma boa solução sim :) porque é exatamente esse o meu problema, nem todas as músicas são tocadas da forma como implementei o código, não quer dizer que um dia não sejam escolhidas mas é mais difícil.
-
Uma sugestão talvez ainda mais fácil, é copiar a lista e fazer trocas (swap) aleatorias dos elementos. O numero de trocas e a posição dos elementos a trocar é aleatória.
Baralhar a lista :)
Neste caso a lista, os elementos são os indices relativos à lista original.
-
Nas questões das musicas até o meu radio, em modo mix de escolher musicas aleatórias consegue nao tocar as musicas todas, e ainda consegue repetir algumas..
Se calhar fazer random, não tem de ser tão random. Por exemplo quando calhar número que ja tenha saido faz random a lista que nunca tenha saido.