News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

Random & Seed Question (PIC12F1572)

Started by Maggie, Mar 27, 2021, 05:21 PM

Previous topic - Next topic

Maggie

Hello,

I have written code that generates a Random number below 10,000 (Using Seed and Random) so I can use the result as a Random start-up delay in ms at the beginning of my code when first powered up (Using Proton compiler Version 3.7.3.6)
I tried this on a PIC12F1571 and it works perfectly. Each time the pic is powered up their is a 1 to 10 second delay before it continues.

However, as I have now finished the rest of the main code, it put me over the flash limit of the 12F1571 so I replaced the part with a 12F1572.
But since doing this the random number generator always produces the same number (Dec 1675 I think it was).

Is their any reason why Random and Seed does not work correctly on the 12F1572 but will on a 12F1571? or I am I doing something wrong here and need to change the seed value to something other than $0345.

Any ideas? Also what does Seed actually do? And how do I use the Seed command, perhaps that's something to do with it. I cannot find much information about using Seed.

Thanks.

Paul

top204

Random functions on a microcontroller or microcomputer are pseudo random number generators, so they always follow the same calculation based upon a "seed" value first loaded into them.

The Seed command is the same as some languages call "Randomize", and places a value in the pseudo random number generator's pot. Then each Random command updates the pot with the result of the pseudo random number generated, ready for the next time.

The only way to get a true random number is to have a true random source to use as a "Seed" value.

If using a program with human activity, a simple method of getting a bit more randomnes is to time a button press, and the length of the button press is the number to place into the Seed command, because the button will rarely be pressed for the same length of time again.

I did create a true random number generator library using an ADC channel to get the random bit patterns that were joined together to create random values, but they were destroyed when the old forum was so, "thoughtlessly" removed. I'll see if I can find them and upload on this forum

I'll see if I can add a bit more detail to the Seed command's explanation in the manuals.

Maggie

#2
Hi Top204,

Thanks for your reply.
It does not have to be truly random as such, but for this project there will be many 100's of devices that all power up at the same time from the same supply.
I then want the main code to start on each one at a different time up to 10 seconds, or mostly different, it won't hurt if a few are the same or close to each other. The first part of my code just requires a random 1 to 10,000 mSec delay at start up so that all the modules do not start running the main code at exactly the same time.

This worked well using a 12F1571 device (A different start-up delay up to 10 secs when powered up) but does not work on a 12F1572, I don't know why? I get a the same fixed number always with the 72 part (Dec 1675).
So if this was the same code on 100 pics, would they all have the same pseudo random number generated? Or would they be pseudo random between devices?
This was only tested on one device so I don't know how this would behave between different devices.
 
The main code also reads in two values from two ADC channels so I could sort of use that as a seed value maybe, or maybe a calculation between to two ADC values to give a suitable seed number range.

I know the code below will give the same result  with many different random numbers, such as 400, 200, 100, 50 etc will all result with a delay of 6.25 Secs but that's ok. As long as the delays between different pics is mostly different, even if it was 25% (1 in 4) would be ok.


Seed $0345
time_delay = random

    While time_delay > 10000                 '10 Second max time (ms), /2 until time_delay < 10 Sec
        time_delay = time_delay / 2
    Wend

RsOut "Time Delay:  ",Dec time_delay, $0D
DelayMS time_delay                           


'.....Main code here.......



Any further thoughts on this?


Thanks

Paul


trastikata

Can't you use the ADC to measure the internal temperature of the die and the fixed voltage reference and then from both values make a third "unique" one?

Maggie

Hi,

yes, that's an idea, but do you mean that the third unique value would be my delay (After calculation to get it to the right range) or use that value as the seed?

Might be a good idea I can try.
I would still like to know why the Random / Seed value I get on the 12F1572 is always the same compared to the 71 version.

Thanks

Paul

trastikata

Hello,

my thought was to use that third value as Seed parameter for the Random function. Something like this:

Dim Temperature_ADC as Word
Dim Voltage_Ref_ADC as Word
Dim Random_Value as Word

MAIN:
    GoSub GET_TEMPERATURE_ADC
    GoSub GET_VOLTAGE_REFERENCE_ADC

    Seed = Temperature_ADC + Voltage_Ref_ADC
    Random_Value = Random

    'Scale the random value between 1 and 10000
    If Random_Value > 10000 then
        Random_Value = (Random_Value / 100) + Seed
    EndIf

    DelayMS Random_Value

GET_TEMPERATURE_ADC:
    'Get internal temperature as 10-bit ADC value
Return

GET_VOLTAGE_REFERENCE_ADC:
    'Get internal voltage reference as 10-bit ADC value
Return

top204

#6
QuoteI would still like to know why the Random / Seed value I get on the 12F1572 is always the same compared to the 71 version.

They aren't different. Both devices are enhanced 14-bit core types and use "exactly" the same code to generate the pseudo random number, so they will produce "exactly" the same results. If a Seed command is not used in the user's BASIC program, the compiler automatically loads the pseudo random number system variables with the value $0345, because they cannot be set to 0, otherwise, no pseudo random numbers would be generated.

For example... With a simple BASIC program:
    Device = 12F1571
    Declare Xtal = 16

    Dim MyByte As Byte
   
    MyByte = Random

The Asm generated on a PIC12F1571 device is:

__random_
    movf PP_RNDH,W
    iorwf PP_RND,W
    btfsc STATUS,2
    incf PP_RND,F
    movlw 128
    btfsc PP_RND,4
    xorwf PP_RNDH,F
    btfsc PP_RND,2
    xorwf PP_RNDH,F
    btfsc PP_RND,1
    xorwf PP_RNDH,F
    rlf PP_RNDH,W
    rlf PP_RND,F
    rlf PP_RNDH,F
    movf PP_RND,W
    return
_compiler_main_start_
    movlw 0X45
    movwf PP_RND
    movlw 0X03
    movwf PP_RNDH
;---------------------------------------------
; START OF THE USER'S PROGRAM CODE
F1_SOF equ $ ; TEST_14E_VER2.BAS
    movlb 0X03
    clrf ANSELA
    movlb 0X02
    clrf CM1CON0
    movlb 0X06
    clrf SLRCONA
    movlb 0X07
    clrf INLVLA
F1_000007 equ $ ; in [TEST_14E_VER2.BAS] MyByte = Random
    movlb 0x00
    call __random_
    movwf MyByte
F1_EOF equ $ ; TEST_14E_VER2.BAS
_pblb__2
    bra _pblb__2

And the Asm code generated for a PIC12F1572 device is:

__random_
    movf PP_RNDH,W
    iorwf PP_RND,W
    btfsc STATUS,2
    incf PP_RND,F
    movlw 128
    btfsc PP_RND,4
    xorwf PP_RNDH,F
    btfsc PP_RND,2
    xorwf PP_RNDH,F
    btfsc PP_RND,1
    xorwf PP_RNDH,F
    rlf PP_RNDH,W
    rlf PP_RND,F
    rlf PP_RNDH,F
    movf PP_RND,W
    return
_compiler_main_start_
    movlw 0X45
    movwf PP_RND
    movlw 0X03
    movwf PP_RNDH
;---------------------------------------------
; START OF THE USER'S PROGRAM CODE
F1_SOF equ $ ; TEST_14E_VER2.BAS
    movlb 0X03
    clrf ANSELA
    movlb 0X02
    clrf CM1CON0
    movlb 0X06
    clrf SLRCONA
    movlb 0X07
    clrf INLVLA
F1_000007 equ $ ; in [TEST_14E_VER2.BAS] MyByte = Random
    movlb 0x00
    call __random_
    movwf MyByte
F1_EOF equ $ ; TEST_14E_VER2.BAS
_pblb__2
    bra _pblb__2

The Asm code listings above are copied from actual Asm listings from the BASIC code with the device changed, and as can be seen.... They are exactly the same Asm code, because they are on the same core type.

top204

This may be of interest to you, and can easily be adapted for an enhanced 14-bit core device by changing the setup for the ADC used. I wrote it a few years ago, and have used it several times in projects.

Really Random Library


Maggie

Hi,

Thank you or all your replies, that's a massive help.
I will now test the 1572 device again, because I also thought it was the same core device and should have worked the same as the 71 version. Must be my code!!

I will also try the ideas regarding the Random number and test out some code using the ADC values etc for the Seed parameter. Looks ok and straight forward.

Thanks again.

Paul

Stephen Moss

Another method of changing the seed at a start up and producing more randomness is to store the seed in EEPROM or HEF. Assuming the memory is clear at purchase (i.e. all location contain 0) then you could do something like this...
Read 1st available memory location
If ValueInMemory = 0 then seed = $1234 (or whatever value you want)
else
Seed = ValueInMemory
End If

Do a Loop to create 10 random numbers and store the 10th in the 1st Memory Location to use as the seed the next time the PIC powers up. Otherwise as others have said your seed value will always be the same and so the sequence of random values generated would also be the same, or if a device has a battery backed clock using the current date/time as the seed would also add more randomness.

OG

#10
Quote from: Stephen Moss on Mar 29, 2021, 11:15 AMAssuming the memory is clear at purchase (i.e. all location contain 0) then you could do something like this...
This value should be FF (3FF for 1572), right?

Stephen Moss

Thinking about it you are probably right, either way as long as the factory default (be it $00 or $FF) is known you can check against its value to determine if the fixed seed value or the one from memory should be used when the program starts.