6 outputs, random sequence random times

#1
Hello

This is my first post here. I have done quiote a few simple Picaxe projects over the years but this one is made more complicated by the need for randomness.

I am looking for some code that will trigger 6 output pins in a random order, and at random times within a short time frame, say 5 seconds.

My current thought process is to generate 6 random numbers, then initiate a while loop which has 6 if statements in. Each if statement checks a counter against the generate random number (and also checks its not matched on a previous loop), if it matches it triggers the associated pin in not it increments the counter and carrys on looping until all 6 have been triggered.... clear as mud? This works apart from the random numbers all just an increase on the last. So they are random but they just increase in value. Therefore the triggers do happen at random times but always in the same order.

I have done lots of reading on random and how it's not random, but suedo random and is seeded from the last number so I am guessign this might be why. I have also tried seeding random with different prime numbers but again the values always come out in teh same order.

I was wondering if anyoen had any advice on how to make this work in the way i'm currently doing it or have any bright ideas on how to achieve it another way.

Thanks in advanced for your time
 

RNovember

Well-known member
#2
If I understand the specifications above, you need something that will set one of six pins to high at random, and hold it high for a random amount of time, and then set another pin to high at random, and keep it on for a random amount of time, on and on and on...

But first we need to know the type of chip you are using.
 
#3
Hello

I should probably give a bit more detail. It is for a fancy doorbell. 6 Tibetan Bowls each with a 12v solenoid to make it "bong". The picaxe chip (18M2) does a pulsout on a pin which triggers a relay that then gives 12v to the solenoid.

So yes, on a button push, 6 pins need to pulsed at random times in a random order, over a short space of time, say 5 second because its doorbell. The next time the doorbell is rung then sequence and timing need to be different, random every time.

The chip is an 18M2

Thanks
 

RNovember

Well-known member
#4
Something like this might work. If you had a set-reset latch, you could use it in a way so that when the doorbell button is pressed, the picaxe gets power. Then after it goes through its dinging routine, it sets the reset on the latch high, and the picaxe quits getting power.

Code:
#picaxe 18m2
dirsb = %11111111
dirsc = %00000000
poke 80, 0

readadc c.0, b4
random b4
let b4 = b4//5 + 1

let time = 0

do while time < b4
    random w0
    let b2 = b0%6

    peek 80, b3
   
    do while b2 = b3
        random w0
        let b2 = b0%6
    loop
       
    poke 80, b2
       
    if b2 = 0 then
        outpinsb = %00000001
    elseif b2 = 1 then
        outpinsb = %00000010
    elseif b2 = 2 then
        outpinsb = %00000100
    elseif b2 = 3 then
        outpinsb = %00001000
    elseif b2 = 4 then
        outpinsb = %00010000
    elseif b2 = 5 then
        outpinsb = %00100000
    else
        sertxd("Something went wrong", cr, lf)
    endif
   
    pause 500
loop

high b.7
pause 100
This code waits for power, and then for a random number of seconds, 1-5, it sets w0 to random, sets the appropriate pin high, and then waits for .5 seconds, and then keeps doing that until it runs out of time.
 

hippy

Technical Support
Staff member
#5
One way to handle the randomising is to treat it like having six cards, numbered 1 to 6, one per bell, laid out in front of you. Throw a dice ( your random number ), take the Nth card along and swap that with the left-most.

Start with :123456
Roll a 5. Swap the 5th along (5) with the first (1) -> 523416
Roll a 3. Swap the 3rd along (3) with the first (5) -> 325416
Roll a 4. Swap the 4th along (4) with the first (3) -> 425316

Do that often enough and one should end up with a jumble. If shuffling while waiting for the doorbell to be pushed it's probably going to be pretty random each time. You can run this in simulation to get a feel for how it works -
Code:
b0 = 0 : b1 = 1 : b2 = 2
b3 = 3 : b4 = 4 : b5 = 5

Do
  For b6 = 0 To 10
    Gosub Shuffle
  Next
  SerTxd( #b0,#b1,#b2,#b3,#b4,#b5, CR, LF )
Loop

Shuffle:
  Random w10
  bPtr = w10 / 17 // 6 ; Where to swap with
  b7 = b0              ; Get the current b0 value
  b0 = @bPtr           ; Set b0 to what we are swapping
  @bPtr = b7           ; Set the swapped to what b0 was
  Return
You could do the same with a set of five cards for the gaps between each bell ring
 

AllyCat

Senior Member
#6
Hi,

IMHO it would be better if the OP had posted his own program code. The description in #1 seems well thought-out, so there might be just a simple coding error.

The PULSOUT driving of the pins could be quite important to give a clean and efficient bell strike; I wonder if you might need to restrain the "random" delay between operations to rather longer than a potential "zero" time, to avoid apparent "clashes". Also, the sequence is not truly a "random" function, because once a bell has been struck it must be removed as a future candidate (as was described).

The code in #4 doesn't simulate well for me. A few suggestions: RANDOM doesn't work correctly with byte values so I'd avoid RANDOM B4. Also READADC might give a useful random seed, but it could be just locked at zero (hippy's method of reading from EEPROM and updating, is better). The TIME variable only increments once each second so won't give much of a "random" interval (and sadly doesn't even reduce at higher clock frequencies). The DO WHILE B2 = B3 loop won't give much delay and the long conditional block at the end could be replaced by:
Code:
lookup b2,(1,2,4,8,16,32),b2
outpinsb = b2
Or simply PULSOUT B2,WIDTH where B2 is assigned the PORT.PIN number.

Cheers, Alan.
.
 
Last edited:

RNovember

Well-known member
#7
Hi, A few suggestions: RANDOM doesn't work correctly with byte values so I'd avoid RANDOM B4. Also READADC might give a useful random seed, but it could be just locked at zero (hippy's method of reading from EEPROM and updating, is better). The TIME variable only increments once each second so won't give much of a "random" interval (and sadly doesn't even reduce at higher clock frequencies). The DO WHILE B2 = B3 loop won't give much delay and the long conditional block at the end could be replaced by:
Code:
lookup b2,(1,2,4,8,16,32),b2
outpinsb = b2
Or simply PULSOUT B2,WIDTH where B2 is assigned the PORT.PIN number.

Cheers, Alan.
.
I didn't realize that random doesn't work on bite variables. I just searched a quick explanation online and put together the code from there.
The DO WHILE B2 = B3 loop is to keep the same pin from being played twice or more in a row.
 

AllyCat

Senior Member
#8
Hi,

Yes, there are quite a lot of "gotchas" with the RANDOM function. I've explained a few in a detailed Code Snippet thread. The need for a word variable is explained in the second paragraph of the Conclusion.

Ah, the WHILE B2 = B3 loop may prevent the same bell being rung twice consecutively, but it needs an "array" of 6 variables (which might be 6 flag bits in a single byte) to record that none of the 6 bells is rung more than once.

Cheers, Alan.
 
#9
Hello All

Thank you very much for your help. Very useful

I really like the idea of cards that Hippy suggested, that produces by far the best selection of random numbers I've seen. As suggested this runs in the background all the time. I used this determine the order in which the outputs are triggered, and then used this order backwards for the time delay between triggering each individual output, once its been multiplied by 1000 and converted to a word for the pause function.

Works a treat.

There will be some fine tuning of the pulsout times once we have the bowls but I think the hard part is now complete.

Thanks again
 
#10
Hello All

Thank you very much for your help. Very useful

I really like the idea of cards that Hippy suggested, that produces by far the best selection of random numbers I've seen. As suggested this runs in the background all the time. I used this determine the order in which the outputs are triggered, and then used this order backwards for the time delay between triggering each individual output, once its been multiplied by 1000 and converted to a word for the pause function.

Works a treat.

There will be some fine tuning of the pulsout times once we have the bowls but I think the hard part is now complete.

Thanks again
Hippys always right ...so I bought the book "how to beat hippy at some kind of picaxe coding for DUMMIES 2019!"
now just waiting on the book tutor :) ... joking!


for my two cents ...if I remember correctly Allycat did a awesome information about reading the temperature on the picaxe chip
which is never accurate so couldn't a person use that code for random since the temperature never gives stable readings
or maybe it was my messed up code :)
 
#11
Since each press of the doorbell button is likely to have a distinct 'on' time, surely this could be measured/timed and used as a seed for the random numbers used for the bell pattern.
 

hippy

Technical Support
Staff member
#12
Since each press of the doorbell button is likely to have a distinct 'on' time, surely this could be measured/timed and used as a seed for the random numbers used for the bell pattern.
Or just keep kicking the random number, or 'shuffling the cards', while waiting between button pushes, which will be a random amount of time.
Code:
Do
  Gosub KickRandmNumber
  If pinC.0 = 1 Then
    Gosub Pushed
    Do : Loop While pinC.0 = 1
  End If
Loop
Because it will be a random time from power-up to first push the random number doesn't need seeding whenever it starts.
 
Top