Python Forum

Full Version: a complicated randomized function which I'm stuck on
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi
I have a function that I can run at a specific time of the day, but I'd like to change it and I cannot get my head round the process.

I'd like the function [ def Flash(): ] to flash in total between 10,000 and 15,000 each day
I'd like the start time to start between [06:00 and 07:00] randomly
and the end time between [22:00 and 23:00] randomly
during it's working hours it can flash a random amount of times
at the end of it's working day it must have flashed between 10,000 adn 15,000 times.


does anyone have any idea how that can be achieved

thanks
What would you like to flash?
A Led ?

Paul
You forgot to post the code
it's actually a motor that'll swing a cat toy...thought it'd be easier to say it was a flash function.

I have no code yet, I'm still at the stage of trying to work out some pseudo code and then determine if it's viable for my skill level (quite low) or if I'd need a fiverr coder to do it

thanks
OK, a motor (stepper, servo, etc) doesn't matter.
I think it is feasible, but are we right in assuming that you
will 'flash' the python program to some controller, that will actualy drive the motor?
The controller may use micropython, that needs to be taken into acount for some functions.
So what is the hardware setup?
Paul
I have the motor all setup and working. I can call my function at a specfic time which is what is happening now, I'd just like to randomize it so that cat doesn't know when it'll activate and entertain him.

thanks
As stated in post #3, we would like to see the code,
because we don't want to find ourselves barking up the wrong tree.

Paul
Hi
here's the code. I think i've gone down the wrong rabbit hole, as it is very predicable and regimented, not very random.
It should run on anyones python and you'll see why I don't think it's very random.
what I

thanks
# Python Script

#import RPi.GPIO as GPIO          
from datetime import datetime, time
from time import sleep
import random, sys

 
in1 = 24
in2 = 23
en = 25
temp1=1


#GPIO.setmode(GPIO.BCM)
#GPIO.setup(in1,GPIO.OUT)
#GPIO.setup(in2,GPIO.OUT)
#GPIO.setup(en,GPIO.OUT)
#GPIO.output(in1,GPIO.LOW)
#GPIO.output(in2,GPIO.LOW)
#p=GPIO.PWM(en,1000)
#p.start(25)

def getTime(h):
    return h[:2] + ':' + h[2:]

def CalculateStart_EndTime():
    global starthour, startminute, endhour, endminute, totalminutesawake, number_of_swings, Target_for_today, starttime, endtime
    Target_for_today = random.randint(15000,20000)
    starthour = random.randint(6,8)
    startminute = random.randint(0,10)
    endhour = random.randint(20,23)
    endminute = random.randint(0,59)
    totalminutesawake = ((60-startminute)+(endminute)+((endhour-(starthour+1))*60))
    if startminute < 10 :  startminute="0"+str(startminute)
    starttime = getTime("0"+str(starthour)+str(startminute))
    
    if endminute < 10 :  endminute="0"+str(endminute)
    endtime = getTime(str(endhour)+str(endminute))
    
    print "I'm going to run for a total of",totalminutesawake,"minutes, starting at",starttime,"ending at",endtime
    number_of_swings = random.randint(10, totalminutesawake)
    print "I'm going to run",number_of_swings,"times today to get to",Target_for_today,"swings"
 

def CalcuateActualStartTimes():
    # For the total number of swing points (number_of_swings) calculate how long after waking up it should start
    global startdelay
    startdelay = [0]
    tmpstartdelay=[0]
    number_of_swings_still_todo = number_of_swings
    Target_for_today_still_todo = Target_for_today
    # for 1 > number of swings to make, get a random number. that random number will be the time delay since the start time to do (Target_for_today/number_of_swings swings each time)
    print "number_of_swings",number_of_swings
    for i in range(1, number_of_swings):
        delay = random.randint(0,totalminutesawake) # get a random number of minutes to delay from waking up
        startdelay.append(delay)
        
    #I've now got a whole lot of time delays, I need to order them
    startdelay.sort()
    #remove duplcates
    [tmpstartdelay.append(x) for x in startdelay if x not in tmpstartdelay] 
    startdelay = tmpstartdelay
    
    #Now I now how many times I will swing, I need to calc the avg number of swings 
    Avg_number_of_swings_to_take_each_time = Target_for_today/len(startdelay)
    # this is how many swings I'd take in the day 
    predicted_swings_done_using_avg_swings = len(startdelay) * Avg_number_of_swings_to_take_each_time
    
    #Check if it'd be enough swings in the day to meet the 15000 requirement
    while predicted_swings_done_using_avg_swings < 15000:
        Avg_number_of_swings_to_take_each_time = Avg_number_of_swings_to_take_each_time + random.randint(1,5)
        predicted_swings_done_using_avg_swings = len(startdelay) * Avg_number_of_swings_to_take_each_time     
    print "I'd take",predicted_swings_done_using_avg_swings,"in the day if I use the average swings each time"

    for i in startdelay:
        print(i)
    print "I swung",len(startdelay), "times today with",Avg_number_of_swings_to_take_each_time,"swings each time"
    print "that means i swing every",  totalminutesawake/len(startdelay),"minutes"
  
 

def StartRunning():
    #Set it to turn forwards
    GPIO.output(in1,GPIO.HIGH)
    GPIO.output(in2,GPIO.LOW)

    #set the run speed to fast
    p.ChangeDutyCycle(50)
     
def Stoprunning():
    GPIO.cleanup()
    #print("GPIO Clean up")



def CheckIfCurrentTimeIsWithinRange():
    now = datetime.now()
    if time(int(starthour),int(startminute)) <= now.time() <= time(int(endhour),int(endminute)):
        print "I should be running now since it's",now.time().strftime("%H:%M")



CalculateStart_EndTime()  
CalcuateActualStartTimes()
CheckIfCurrentTimeIsWithinRange() 
#print("run")
#StartRunning()
#sleep(5)
#print("stop")
#Stoprunning()
Hi,
Difficult to run for me, as it is written in python 2. for RPI or similar.
For what i can see, and if i get this right:
You want to activate the swing between 15 and 20.000 times, and then swing a random number of times (1 to 5).
This between 6 and 23 hours max. That are 61.000 secs, so on average you need to activate every +/- 3 seconds.
You go a long way to calculate everything beforehand, why don't you reverse the steam. It will save you a lot of code
and be more random. I mean , write a function that starts at 6.00 and stops at 23.00, and 'sleeps' for random times
of between 1 and 6 secs e.g. Then swings a random number of times .
If you want, you can count every activity and report at the end of the day.
You could simulate the whole thing to tune for the best results.

Another possibility is to calculate a random start-end time, the average number of sleep seconds between activation and swings,
write that to a long 2D list, and just let it run. That way you now everything beforehand.
my 2 cts,
Paul
Agree with DPaul above, would add that when calculating the random times it does not need to be uniform. For example, random.gauss(mean, std) gives you random numbers centered on mean with a standard deviation of std. 95% of the values will fall within 2 SDs of the mean, and 99% within 3 SDs. Set your mean and then you can experiment with what SD works best (larger SD will appear more random).
Pages: 1 2