Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC Random Lookup Table

Status
Not open for further replies.

mark squared

New Member
Hello, I am new to PIC programming and I could really use your assistance in my code. I would like to make a random output on Port D using only 5 bits. I attempted different ways to make the lookup table pick a different line in the lookup table but it would not work at all. I’m using a PIC 18F4550 microcontroller that outputs to Port D to turn on a LED's. I'm only using bits 0 to 4, 5 bits from the lookup table below. I would like to randomly choose a line in the lookup table and output it to Port D.
Can someone help me in by modifying the code to randomly pick a line in the lookup table? I would greatly appreciate it. Thanks Mark Squared.




MAIN
GOTO Start
GOTO MAIN


Start clrf count ;set counter register to zero
Read movf count, w ;put counter value in W
call Table
movwf PORTD
call Delay
incf count, w
xorlw d'14' ;check for last (14th) entry
btfsc STATUS, Z
goto Start ;if start from beginning
incf count, f ;else do next
goto Read

Table ADDWF PCL, f ;data table for bit pattern
retlw b'10000000'
retlw b'01000001'
retlw b'00100010'
retlw b'00100100'
retlw b'00000000'
retlw b'00000100'
retlw b'00000010'
retlw b'00000001'
retlw b'00000010'
retlw b'00000100'
retlw b'00001000'
retlw b'00010000'
retlw b'00100000'
retlw b'00000100'




Delay
;return; added for testing
movlw d'250' ;delay 250 ms (4 MHz clock)
movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00

end
 
Have a look at this code. If you call it 4 times, load W from Random, AND it with 15, check it is in range (call again if not) and then look up your table.

Mike.
 
Hi Mike (Pommie)

Thank you for your quick response. I tried what you said but it did not work, probably because I don’t know what I am doing. Please see my code below for what I did. If a number is placed into the variable “count” like example the number 5 will the pointer go to that line in the lookup table line number 5?
Thank you for your help.


MAIN
GOTO Start
GOTO MAIN


Start clrf count ;set counter register to zero
Call Rand ;New code
Call Rand ;Call Rand 4 times
Call Rand ;New code
Call Rand ;New code
MOVF Random,W ;New code
ANDLW d'15' ;New code
XORLW d'15' ;test with 15, ;New code
btfsc STATUS, Z; ;New code
CALL Rand ;if not 15 call Rand one mor time again;;New code
MOVF Random,W ;move # in Random to count number in table.

Read movf count, w ;put counter value in W
call Table
movwf PORTD
call Delay
incf count, w
xorlw d'14' ;check for last (14th) entry
btfsc STATUS, Z
goto Start ;if start from beginning
incf count, f ;else do next
goto Read

Table ADDWF PCL, f ;data table for bit pattern
retlw b'00001000'
retlw b'00000001'
retlw b'00000010'
retlw b'00000100'
retlw b'00000000'
retlw b'00000100'
retlw b'00000010'
retlw b'00000001'
retlw b'00000010'
retlw b'00000100'
retlw b'00001000'
retlw b'00010000'
retlw b'00000100'
retlw b'00001000'

;;New code Rand
Rand rlcf Random,w ;shift and move to W
andlw 0x82 ;keep bits 7 and 1
addlw 0x7e ;xor into bit 7
addlw 0x80 ;move to carry bit
rlcf Random,f ;shift into seed
return



Delay
return; added for testing
movlw d'250' ;delay 250 ms (4 MHz clock)
movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00

end
 
You're still using count!

Try,
Code:
Start		movlw	.123
		movwf	Random

Read		call	Rand		;New code
		call	Rand		;Call Rand 4 times
		call	Rand		;New code
		call	Rand		;New code
		movf	Random,W	;New code
		andlw	d'15'		;New code
		sublw	d'13'		;allow 0 to 13 only
		btfss	STATUS,C	; ;New code
		goto	Read		;if not 15 call Rand one mor time again;;New code
		movf	Random,W	;move # in Random to count number in table.
		andlw	.15
		call	Table 
		movwf	PORTD
		call	Delay
		goto	Read

mike.
 
If you don't need a high quality randomness (like Pommie's code) ie if this is for a simple random app like "flickering flame LEDs" then there are a couple of other options;

You could just use a large table instead of the 14 entry table you have, so the randomness is just part of the table.

You could use a large table AND just grab every 7th value in turn, this provides additional randomness from the x/7 aliasing error.

You could use a simple algorithm to generate the 5 bits directly. You only seem to have one bit active at one time so you could just choose a random bit out of the 5 each time.
 
Thank you for your help Mike and Mr.RB,

Mike your code works great all by itself but when I put in my main code of the program it does not work. I tested the code in MPLAB with Stimulus and watch windows to look at the ports and number values. When the Random call is complete and it goes to the table an error happens and the pointer moves to other sections of the program because it is lost. What is the problem with the random? Is the value of random to Large for the table or a code layout problem?
Copy the code into MPLAB and you will see the issue I am having.

I am trying to make a whack-a-mole type game with the code. The code initializes the ports I am only using portB input, portC output, and portD output. In portB input is reading to start. PortB is reading the bits RB0 is timeout, RB1 is slow delay speed, and RB2 is fast delay speed for action. PortC is for setup of external devices like clear score and timer start. PortD is for the 5 moles LED lights. I have two speeds fast and slow for portD. Maybe there is a better way to do random with delay on the one led at a time to portD. I really appreciate your help.

Thank you. Mark



Code:
;______________________________________________________________
    LIST P=18F4550        ;directive to define processor
    #include <P18F4550.INC>    ;processor specific variable definitions
    #include "migrate.inc" 
    Errorlevel -302

;******************************************************************************
;Configuration bits
;Microchip has changed the format for defining the configuration bits, please 
;see the .inc file for futher details on notation.  Below are a few examples.
;   Oscillator Selection:
    ;CONFIG    FOSC = HS         ;XT oscillator, XT used by USB
    config FOSC = HSPLL_HS ; HS
    config PLLDIV = 5 ; PLL prescaler i.e. 20/5=4 MHz (96MHz PLL)
    config CPUDIV = OSC1_PLL2 ; PLL divided by 2 (96/2=48MHz) to feed CPU;
    config USBDIV = 2 ; if full speed (FSEN=1) USB is fed by PLL
    ; divided by 2 (96/2=48MHz)
    config IESO = OFF
    config PWRT = OFF
    config BOR = OFF
    config BORV = 2
    config VREGEN = ON
    config WDT = OFF
    config WDTPS = 32768
    config MCLRE = OFF
    config LPT1OSC = OFF
    config PBADEN = OFF
    config CCP2MX = OFF
    config STVREN = OFF
    config LVP = OFF
    config ICPRT = OFF
    config XINST = OFF
    config DEBUG = OFF
    config CP0 = OFF
    config CP1 = OFF
    config CP2 = OFF
    config CPB = OFF
    config CPD = OFF
    config WRT0 = OFF
    config WRT1 = OFF
    config WRT2 = OFF
    config WRT3 = OFF
    config WRTB = OFF
    config WRTC = OFF
    config WRTD = OFF
    config EBTR0 = OFF
    config EBTR1 = OFF
    config EBTR2 = OFF
    config EBTRB = OFF
        
;******************************************************************************
;Variable definitions
; These variables are only needed if low priority interrupts are used. 
; More variables may be needed to store other special function registers used
; in the interrupt routines.

        CBLOCK    0x080
        WREG_TEMP    ;variable used for context saving 
        STATUS_TEMP    ;variable used for context saving
        BSR_TEMP    ;variable used for context saving
        RAND1        ;random file
        SENSTAT        ;veg status hit-delay-over
        BUTTON1        ;start veg
        ;INT_PORTS
        Random
        count1
        counta
        countb
        DEALY25
        DEALY50
        DEALY100
        CounterA    
        CounterB    
        CounterC    
        EXAMPLE        ;example of a variable in access RAM
        ENDC
                    
;******************************************************************************
;EEPROM data
; Data to be programmed into the Data EEPROM is defined here

    ORG    0xf00000

    DE    "Test Data",0,1,2,3,4,5

;******************************************************************************
;Reset vector
; This code will start executing when a reset occurs.

    ORG    0x0000

    goto    Main1        ;go to start of main code

;******************************************************************************
;High priority interrupt vector
; This code will start executing when a high priority interrupt occurs or
; when any interrupt occurs if interrupt priorities are not enabled.

    ORG    0x0008
    bra    HighInt        ;go to high priority interrupt routine

;******************************************************************************
;Low priority interrupt vector and routine
; This code will start executing when a low priority interrupt occurs.
; This code can be removed if low priority interrupts are not used.

    ORG    0x0018
    ;movff    STATUS,STATUS_TEMP    ;save STATUS register
    ;movff    WREG,WREG_TEMP        ;save working register
    ;movff    BSR,BSR_TEMP        ;save BSR register



    

;    movff    BSR_TEMP,BSR        ;restore BSR register
;    movff    WREG_TEMP,WREG        ;restore working register
;    movff    STATUS_TEMP,STATUS    ;restore STATUS register
;    GOTO HOLD
;    retfie

;******************************************************************************
;High priority interrupt routine
; The high priority interrupt code is placed here to avoid conflicting with
; the low priority interrupt vector.


HighInt:;    *** high priority interrupt code goes here ***
OVER
    MOVLW B'00000000'     ;all Veg down
    MOVWF PORTD
    MOVLW B'00000010'     ;RC1 time gate reset
    MOVWF PORTC
    CALL    DELAY100
    MOVLW    b'00000000'    ;
    MOVWF     INTCON;,GIE
    CLRF   BUTTON1
    GOTO     HOLD_INT
    ;retfie    FAST
; Start of main program
; The main program code is placed here.

Main1: 
    GOTO INT_PORTS    

Main2
    GOTO HOLD
    GOTO Main2

;**********  INITIALIZING   ***********
INT_PORTS
        CLRF    UCON    ;disable usb
        CLRF    LATA    ;clear latches
        MOVLW    07h    ;turn off compartors
        MOVWF    CMCON
        CLRF    PORTA    ;******PortA INPUT not used
        MOVLW    0Fh
        MOVWF    ADCON1
        MOVLW    0fh        ;inputs
        MOVWF    TRISA
        CLRF    PORTB    ;*****PortB INPUT
        CLRF    LATB    ;clear latches
        MOVLW    0Fh    ;1111
        MOVWF    ADCON1
        MOVLW    b'11111111'    ;inputs
        MOVWF    TRISB
        CLRF    PORTC        ;*****PortC Output
        CLRF    LATC    ;clear latches
        MOVLW    b'00000000'    ;outputs
        MOVWF    TRISC
        CLRF    PORTD        ;********PortD OUTPUT
        CLRF    LATD    ;clear latches
        MOVLW    b'00000000'    ;outputs
        MOVWF    TRISD
        CLRF    PORTE
        CLRF    LATE    ;clear latches
        MOVLW    07h    ;turn off comparators
        MOVWF    CMCON
        MOVLW    b'00000000'    ;outputs
        MOVWF    TRISE
        MOVLW    b'11011000'    ;
        MOVWF    b'01111111'
        MOVWF    OSCTUNE
        MOVWF    b'00000000'
        MOVWF    WDTCON
        MOVWF     INTCON;,GIE
        bcf     RCON,IPEN ;disable priorities and enable Compatibility Mode 
        GOTO    Main2
;***************************
;clear all ports coming back to the hold function for restart.

HOLD_INT
    MOVLW    b'11011000'    ;restore inturrupts
    MOVWF     INTCON;
    CLRF    PORTA
    CLRF    PORTB
    CLRF    PORTC
    CLRF    PORTD
    CLRF    PORTE

HOLD
    CLRF    PORTB
    CLRF    PORTC
    CLRF    PORTD
    CLRF   Random
    CLRF   BUTTON1
    MOVLW b'00000010'     ;clear latch RC1=time gate reset
    MOVWF PORTC            ;PortC Bits only work RCO,RC1,RC2,RC6, RC7
    CALL   DELAY10
    MOVLW B'00000000'     ;clear portC
    MOVWF PORTC
    MOVLW B'00000000'     ;clear portB inputs
    MOVWF PORTB
    GOTO   HOLD2
    
HOLD2            ;inter loop
    MOVF PORTB,W    ;PORT-B, RB3 (INPUT) Stat Button pressed 
    MOVWF BUTTON1    ;Button 
    MOVF BUTTON1,W
    XORLW     B'00000110' ; Fast-Start Bit0 speed, bit1 start
    BTFSC     STATUS,Z
    GOTO     VegFAST ;goto Fast veg

    MOVF     BUTTON1,W 
    XORLW     B'00000100' ; Slow-start bit0 speed, bit1 start
    BTFSC     STATUS,Z 
    GOTO     VegSLOW    ;goto Slow veg
    GOTO     HOLD2

VegSLOW        ;This is the Main loop to run until timer is complete.
    
SetupS    
    MOVLW B'10000000'     ;s-clear close relay RC7  can start timer same time also RC7.
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000000'     ;S-clear open relay RC7
    MOVWF PORTC
    MOVLW B'00000100'     ;(Start Timer) RC2 high start timer card via opto.    
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000000'     ;(Timer Running) RC2 timer remains running
    MOVWF PORTC
    MOVLW B'00000011'     ;Reset RC1 Time Gate,,RC0=enable time gate    
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000001'     ;RC0 time gate enabled remain on to end
    MOVWF PORTC
    GOTO    SlowRAND

;Best Random Code ----------------------------------------------
SlowRAND    
        movlw    .123
        movwf    Random

ReadS    call    RandS        ;
        call    RandS        ;Call Rand 4 times
        call    RandS        ;
        call    RandS        ;
        movf    Random,W    ;
        andlw    d'15'        ;
        sublw    d'13'        ;allow 0 to 13 only
        btfss    STATUS,C    ; ;
        goto    ReadS        ;if not 15 call Rand one mor time again;;New code
        movf    Random,W    ;move # in Random to count number in table.
        andlw    .15
        call    TableS 
        movwf    PORTD
        call    DelaySlow
        goto    ReadS


TableS    ADDWF   PCL, f            ;data table for bit pattern on PORT D
        retlw    b'00001000'
        retlw   b'00000001'
        retlw   b'00000010'
        retlw   b'00000100'
        retlw   b'00000000'
        retlw   b'00000100'
        retlw   b'00000010'
        retlw   b'00000001'
        retlw   b'00000010'
        retlw   b'00000100'
        retlw   b'00001000'
        retlw   b'00010000'
        retlw   b'00000100'
        retlw   b'00001000'


RandS    rlcf    Random,w    ;shift and move to W
        andlw    0x82        ;keep bits 7 and 1
        addlw    0x7e        ;xor into bit 7
        addlw    0x80        ;move to carry bit
        rlcf    Random,f    ;shift into seed
        return


DelaySlow
    return; added for testing*******Remove    
    movlw    d'250'            ;delay 250 ms (4 MHz-clock)
    movwf    count1
S1    movlw    0xC7            ;change values for speed or call more times
    movwf    counta
    movlw    0x01
    movwf    countb
Delay_S
    decfsz    counta, f
    goto    $+2
    decfsz    countb, f
    goto    Delay_S
    decfsz    count1    ,f
    goto    S1
    retlw    0x00
;-------------------------------------------------------------    
         

VegFAST    ;This is the Main loop to run until timer is complete.
    
SetupF    
    MOVLW B'10000000'     ;s-clear close relay RC7
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000000'     ;S-clear open relay RC7
    MOVWF PORTC
    MOVLW B'00000100'     ;(Start Timer) RC2 high start timer card via opto.    
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000000'     ;(Timer Running) RC2 timer remains running
    MOVWF PORTC
    MOVLW B'00000011'     ;Reset RC1 Time Gate,,RC0=enable time gate    
    MOVWF PORTC
    CALL  DELAY10
    MOVLW B'00000001'     ;RC0 time gate enabled remain on to end
    MOVWF PORTC
    GOTO    FastRAND
;Best Random Code ----------------------------------------------
FastRAND    movlw    .123
            movwf    Random

ReadF    call    RandF        ;
        call    RandF        ;Call Rand 4 times
        call    RandF        ;
        call    RandF        ;
        movf    Random,W    ;
        andlw    d'15'        ;
        sublw    d'13'        ;allow 0 to 13 only
        btfss    STATUS,C    ; 
        goto    ReadF        ;if not 15 call Rand one mor time again;;New code
        movf    Random,W    ;move # in Random to count number in table.
        andlw    .15
        call    TableF 
        movwf    PORTD
        call    DelayFast
        goto    ReadF


TableF    ADDWF   PCL, f            ;data table for bit pattern
        retlw    b'00001000'
        retlw   b'00000001'
        retlw   b'00000010'
        retlw   b'00000100'
        retlw   b'00000000'
        retlw   b'00000100'
        retlw   b'00000010'
        retlw   b'00000001'
        retlw   b'00000010'
        retlw   b'00000100'
        retlw   b'00001000'
        retlw   b'00010000'
        retlw   b'00000100'
        retlw   b'00001000'


RandF    rlcf    Random,w    ;shift and move to W
        andlw    0x82        ;keep bits 7 and 1
        addlw    0x7e        ;xor into bit 7
        addlw    0x80        ;move to carry bit
        rlcf    Random,f    ;shift into seed
        return


DelayFast
    return; added for testing    
    movlw    d'250'            ;delay 250 ms (4 MHz clock)
    movwf    count1
F1    movlw    0xC7
    movwf    counta
    movlw    0x01
    movwf    countb
Delay_F
    decfsz    counta, f
    goto    $+2
    decfsz    countb, f
    goto    Delay_F
    decfsz    count1    ,f
    goto    F1
    retlw    0x00
;-------------------------------------------------------------    



DELAY10
    return ;**********************////??Remove
      movlw     D'25'
      movwf     CounterC
      movlw     D'10'
      movwf     CounterB
      movlw     D'1'
      movwf     CounterA

LOOP10     
    decfsz     CounterA,f
      goto     LOOP10
      decfsz     CounterB,f
      goto     LOOP10
      decfsz     CounterC,f
      goto     LOOP10
      RETURN


        END
 
Last edited by a moderator:
The problem with your code is that it is designed to run on a 16 series chip and your table is in page 1. The 18 series chips use 2 locations per instruction and so the offset needs to be doubled. Also, as you don't place your table at the beginning of your code, you need to calculate the full address.

Try,
Code:
TableS		movwf	temp
		movlw	high(datatab)
		movwf	PCLATH
		rlncf	temp,W
		addlw	low(datatab)
		btfsc	STATUS,Z
		incf	PCLATH,F
		movwf	PCL		;data table for bit pattern on PORT D
datatab		retlw	b'00001000'
		retlw	b'00000001'
		retlw	b'00000010'
		retlw	b'00000100'
		retlw	b'00000000'
		retlw	b'00000100'
		retlw	b'00000010'
		retlw	b'00000001'
		retlw	b'00000010'
		retlw	b'00000100'
		retlw	b'00001000'
		retlw	b'00010000'
		retlw	b'00000100'
		retlw	b'00001000'
Also, why are you repeating subroutines? Just use the same ones in both the slow and fast code.

Edit, when posting code, place [code] before it and [/code] after it so it keeps it's formating as above.

Mike.
 
Last edited by a moderator:
Status
Not open for further replies.

Latest threads

Back
Top