View previous topic :: View next topic |
Author |
Message |
CBailey
Joined: 07 May 2015 Posts: 108
|
Posted: Tue Dec 12, 2023 2:35 pm Post subject: Getting a more random seed from the ADC |
|
|
I accidentally posted this in the Arduino forum but it's not exactly arduino-related.
I grabbed this from an old post by Jabberwocky (https://www.mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&t=8778&highlight=random+seed), but can't get it to work. When I run it, I always get 63 as an output. I haven't had reason to use the ADC yet so I'm probably doing something dumb.
Code: |
$programmer = 22 'ARDUINO (using stk500v1 protocol)
$regfile = "m328pdef.dat" 'Set the AVR to use - ATMega328.
$crystal = 16000000 'Set the AVR clock.
'
$hwstack = 48 'Set the capacity of the hardware stack.
$swstack = 80 'Set the capacity of the software stack.
$framesize = 80
' ---------------------------------------------
' * PCF8574 I2C LCD Adapter settings *
'----------------------------------------------
$lib "i2c_twi.lib" 'Incorporate the hardware I2C/TWI library.
Config Twi = 100000 'I2C bus clock = 100KHz
Config Scl = Portc.5 'You must specify the SCL pin name.
Config Sda = Portc.4 'You must specify the SDA pin name.
I2cinit 'Initialize the SCL and SDA lines of the I2C bus.
Dim Pcf8574_lcd As Byte : Pcf8574_lcd = &H4E 'PCF8574 slave address. (&H40,&H42,&H44,&H46,&H48,&H4A,&H4C,&H4E)
Dim Backlight As Byte : Backlight = 1 'LCD backlight control. (0: off, 1: on)
$lib "lcd_i2c_PCF8574.LIB" 'Incorporate the library of I2C LCD PCF8574 Adapter.
Config Lcd = 16x2 'Set the LCD to 16 characters and 2 lines.
Initlcd
'-------------------------------------------------------
' Here we make a more random seed
'
Dim I as Byte
MakeSeed:
cls
CONFIG ADC = free, PRESCALER = 2
Dim Rnd_word as word
'Dim I as byte
Dim Bit_num as byte
Dim Adc_word as word
lcd "Random Gen:"
Rnd_word = 0
For I = 1 To 255 'n times the whole process to mix the value up well
For Bit_num = 0 To 25
Adc_word = Getadc(0)
Adc_word = Adc_word And 1
Rotate Rnd_word , Left
Rnd_word = Rnd_word Xor Adc_word
Next
Next
''__rseed = Rnd_word 'use random value to set the seed or for whatever
'cls
lcd Rnd_word
waitms 100
Goto MakeSeed
|
(BASCOM-AVR version : 2.0.8.6 ) |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Dec 12, 2023 4:03 pm Post subject: Re: Getting a more random seed from the ADC |
|
|
CBailey wrote: | I haven't had reason to use the ADC yet so I'm probably doing something dumb. |
You got that correct.
1st - read the help, keyword: Config ADC
2nd - think about what a Reference is for.
3rd - open the 'Single'-conversion sample 'adc.bas', make it work
4th - read the appropriate datasheet section
5th - try to switch over to free run
Hint 1, a prescaler of 2 and thus 8MHz ADC-clock results in (13 clocks per sample) 615400 ADC sample frequency, which is far too high.
64, 128 or AUTO as prescaler match better.
Hint 2, as you can get from 1st, the line 'Adc_word = Getadc(0)' won't be compiled, you need to control the 4 MUX-bits in ADMUX and read the value via 'result = ADC' |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 108
|
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Dec 13, 2023 3:53 pm Post subject: |
|
|
CBailey wrote: | I still get a zero output. What am I doing wrong? |
Alas it's not enough to thank me for my reply, if you miss my advice.
1. You need a reference.
If you have physically connected the ARef-pin (see datasheet) of your ATM328 to VCC or another suitable voltage source, then you're fine with parameter 'off', as well without the parameter 'REFERENCE'.
Otherwise you need to tell the compiler which internal source for REFERENCE you want.
As you won't find the AtMega328 mentioned in this context by the help, you can use parameters for m48/88/168, as this is the same processor family.
2. You use 'AdcJunk = Getadc(0)' in your code and I wrote 'the line 'Adc_word = Getadc(0)' won't be compiled'.
Do you think by renaming the variable to AdcJunk anything changes?
I also gave you the solution with 'read the value via result = ADC'. This becomes 'AdcJunk = ADC'
3. Your code contains again 'PRESCALER = 2', while I wrote 'a prescaler of 2 ... which is far too high. 4, 128 or AUTO as prescaler match better.'
This has the effect that the internal sample capacitor of the ADC is charged too often, too fast, which quasi makes the ADC0 pin very low impedance.
What I understand from this approach is, that either a floating or with some noise driven ADC0-pin should be used for randomness.
Sampling too fast may be contra-productive therefor.
4. As you also omitted to care about the ADMUX-register, at least MUX is at its default &b0000, which selects ADC0 as input.
Be aware that you need to control MUX3..0 in case you want to use a different pin than ADC0.
In short, point 2 is the main error, the variable AdcJunk will keep its initial value, which is zero.
Short thereafter point 1 may follow, then in order 3 and 4. |
|
Back to top |
|
|
laborratte
Joined: 27 Jul 2005 Posts: 299 Location: Berlin
|
Posted: Wed Dec 13, 2023 4:43 pm Post subject: |
|
|
@MWS
I agree with point 1 & 3 (and in addition I ask myself: why the heck does this loop has to run 637500 times?), but at least my compiler (2.0.8.1) translates
Code: | adc_word = getadc(0)
| pretty solid to
Code: | lds R16,ADMUX
andi R16,&B11110000 'MUX3:0 = 0
sts ADMUX,R16
'and, for short, in pseudo-word assembler:
lds R24:R25,ADC
ldi X,{adc_word}
st X,R24:R25
|
So, I don't get your point 2. |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Dec 13, 2023 7:48 pm Post subject: |
|
|
laborratte wrote: | but at least my compiler (2.0.8.1) translates pretty solid |
The time I wrote first about GetADC() the result was the way, that while simulating with AVR Studio 4 I was not able to set a breakpoint on ' result = GetADC(0)', simply because this line held no opcodes.
Which was the reason for my statement.
Checked again with a small sample on a fresh 2.0.8.6 and it compiled ok, the ADC-channel can be thus easily set by GetADC(channelx) while in the same the ADC-result is returned.
Which is good news for the TO.
Thank you. |
|
Back to top |
|
|
laborratte
Joined: 27 Jul 2005 Posts: 299 Location: Berlin
|
Posted: Wed Dec 13, 2023 11:37 pm Post subject: |
|
|
MWS wrote: | (...) with AVR Studio 4 I was not able to set a breakpoint (...) |
oh yes, this sounds very familiar to me |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 108
|
Posted: Thu Dec 14, 2023 4:50 am Post subject: |
|
|
Thanks for the replies. I did get it working. Below is my code in the hopes it can help someone.
Code: |
CONFIG ADC = Single, PRESCALER = Auto, REFERENCE = Avcc
Dim Adc_word as word
Dim Bit_num as Byte
Dim Rnd_word as word
For I = 1 To 72
For Bit_num = 0 To 7
Start ADC
Adc_word = Getadc(Bit_num)
Stop ADC
Rotate Rnd_word , Left
Rnd_word = Rnd_word Xor Adc_word
Next
Next
___rseed = Rnd_word
|
I had it loop through all the ADCs as I found some were more random than others. It doesn't appear to be perfectly random but more than enough for my purposes. I turn the ADC on and off in the hopes it might give the ADC a more bumpy ride and spit out more randomness but it didn't appear to make much difference. |
|
Back to top |
|
|
hgrueneis
Joined: 04 Apr 2009 Posts: 902 Location: A-4786 Brunnenthal
|
Posted: Thu Dec 21, 2023 10:34 pm Post subject: |
|
|
One way would be, to feed the ADC with a diode in between AC voltage and use an odd timing to get a random value. you can also combine it with variable data, like seconds and other changing data. Take multiple samples and mathematically result in a random number.
Just an input.
Regards Hubert |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|