![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Hi,
I am working on my first PIC project using a 16F818 and have hit a math problem that currently has me stumped. I am writing the program in PIC Basic but can insert assembly code blocks if required. My problem is as follows: I need to generate a pseudo random number that falls between 1 and 60. I know how to generate the random number (there is a RANDOM command available) and at the moment I have stored this in location 'W1'. However, the number can be between 1 and 65,535 and this is where my math skills are letting me down. I need a way of reducing that random number until it falls into the 1-60 range so that I can then use that figure to generate a delay in seconds based on the new number. I had thought about trying to 'sample' the last 7 bits of the number and just using those (the idea was that it would be between 1 and 63 which is close enough) but cannot find a way to do that. I have also thought about dividing by both 32 and 100 to try to 'shift' the number into the required range but again I have had no luck as I do not know what the number is and therefore how many times I would need to go around a loop to reduce it. Does anyone know of a method where I can either limit the random number to the 1-60 range or a method of reducing some unknown number until it falls into that range? Any help will be gratefully received as I have now come to a complete stop on this project until I can get this sorted. Thanks, Larry |
|
|
|
|
|
|
(permalink) |
|
Hmmmmm........I think I may have just found the answer! :lol:
I was just doing some research when I came across information on 'bitwise operators' and I think this will work for me. Maybe someone can tell me if the following code will work....... NOTE: W1 has already been 'seeded' with a starting number Random W1 .......................'randomise W1 and store in W1 W1 = W1 & %00111111.......'apply AND 'mask' to give #<=63 Pause W1 * 1000.................'pause for W1 secs Can anyone see a problem with the above code? Larry |
|
|
|
|
|
|
(permalink) |
|
Maybe you can multiply the random number W1 with 60 and divide by 65536 (by tuncating the lower 16 bits of the 24-bit product). This results in a random number less than 60. Add the result by 1 and it's 1 to 60 number.
__________________
"Having to do with Motion Control" |
|
|
|
|
|
|
(permalink) |
|
Thanks for that!
I just did some major number crunching on the calculator to check that out and it looks like that will work just fine for what I need. I guess I should have seen that way out but sometimes you can't see the wood for the trees eh! Plus, I have a disability that sometimes leaves me with 'brain fogs' where even simple mental tasks become major chores. :cry: Larry |
|
|
|
|
|
|
(permalink) |
|
OK....now I have something strange going on and I can't seem to find a cure.....can anyone help?
I have written my code and downloaded the "PIC Simulator IDE" demo program to test it on (a great program BTW!) Everything works fine until it gets to the 'PB3' subroutine where my random number/timer code is. Whenever I run the program it seems to delay for exactly the same time and ALWAYS outputs the 'PB2' subroutine (it should randomly select EITHER 'PB1SUB' or 'PB2SUB'). I have searched this forum and others for clues and have tried a number of variations on the code and I still get the SAME delay and only the 'PB2' output. I originally 'seeded' the random generator with a fixed number but then discovered that it will ALWAYS produce the same number by doing this. So after reading another post (elsewhere) I decided to use the length of time the pushbutton was pressed to seed the random generator, but I still get the same delay and the same 'PB2' output to the buzzer pin. I wondered if I was having problems with the 'pause' command and changed every pause to a time wasting loop but it still gives the exact same result. Considering this is my first PIC project I am pleased to have it working this far but I would really like to fully understand this 'random' command and why I can't get the program to actually randomly select one option from a choice of two after a pseudo random time delay of 1-60 seconds. Once again any help will be greatfully received and I have included my code at the end. Larry 'set I/O pins TRISA = %00000000 'set PORTA pins (unused pins as OP) TRISB = %00010110 'set PORTB pins (unused pins as OP) 'rename pins to logical names PBCONTROL VAR PORTB.0 'rename RB0 to PBCONTROL PB1 VAR PORTB.1 'rename RB1 to PB1 PB2 VAR PORTB.2 'rename RB2 to PB2 PB3 VAR PORTB.4 'rename RB4 to PB3 BUZZER VAR PORTB.3 'rename RB3 to BUZZER GLED VAR PORTB.5 'rename RB5 to GLED RLED VAR PORTB.6 'rename RB6 to RLED 'set pin status (high/low) High PBCONTROL 'set PBCONTROL high Low BUZZER 'set Buzzer low High GLED 'set GLED high Low RLED 'set RLED low 'set variables RND VAR WORD 'set RND as variable SPIN VAR WORD 'set SPIN as variable 'set LOOP1 & 2 as variables for loop LOOP1 VAR WORD 'set LOOP1 as variable LOOP2 VAR WORD 'set LOOP2 as variable 'start main routine GoTo Main 'goto main routine 'subroutine list PB1SUB: Low PBCONTROL 'turn off PB's Low GLED 'turn off Green LED High BUZZER 'turn on BUZZER For LOOP1=1 TO 5000 'pause for 5 secs Next LOOP1 Low BUZZER 'turn off buzzer High GLED 'turn on Green LED High PBCONTROL 'turn on PB's GoTo Main 'return to main prog PB2SUB: Low PBCONTROL 'turn off PB's Low GLED 'turn off Green LED For LOOP1=1 TO 5 'set loop1 length for 5 secs High BUZZER 'turn on BUZZER For LOOP2=1 TO 500 'pause for 0.5 secs Next LOOP2 Low BUZZER 'turn off BUZZER For LOOP2=1 TO 500 'pause for 0.5 secs Next LOOP2 Next LOOP1 'go back around loop1 until complete High GLED 'turn on Green LED High PBCONTROL 'turn on PB's GoTo Main 'return to main prog PB3SUB: While PB3=0 'spin for button press time Spin=Spin+21 '21 just speeds things up Wend Low GLED 'turn off Green LED High RLED 'turn on Red LED Low PBCONTROL 'turn off PB's RND=SPIN 'let RND=SPIN Random RND 'randomise RND RND=(RND*60/65535)+1 'truncate RND TO fall between 1 and 60 For LOOP1=1 TO (RND*1000) 'pause for RND secs Next LOOP1 Random RND 'randomise RND again RND=(RND*60/65535)+1 'truncate RND TO fall between 1 and 60 Low RLED 'turn off Red LED IF RND>=30 Then PB1SUB 'if RND is higher than 30 run PB1 sub-routine GoTo PB2SUB 'if RND is lower than 30 run PB2 sub-routine 'main program Main: IF PB1 = 0 Then PB1SUB 'check PB1 status if low go to PB1SUB IF PB2 = 0 Then PB2SUB 'check PB2 status if low go to PB2SUB IF PB3 = 0 Then PB3SUB 'check PB3 status if low go to PB3SUB GoTo Main 'go back to the top and check again End 'end of program |
|
|
|
|