ePIP - endpoints Picked in Proportion/ Perfect Pub Round Load Share demo

This page is a demo/sketch of the ePIP or Perfect Pub round load share in a Microchip PIC. I rechiped a Maplin's Lottery Number picker kit.

The kit is/was available from Maplin who sourced it from MUTR

The requirement is to distribute a stream of calls in proportion to a number of destinations, with the calls spread as evenly as possible, in the proportions specifed, to each destination.

e.g Assume proportions of 4 Parts, 2 Parts, 2 Parts to destinations A,B,C distribute in the Sequence A,B,A,C, would be better than A,A,A,A,B,B,C,C.

This method works for non integer proportions.

ePIP - endpoints Picked in Proportion.

Perfect Pub Round - Each person pays in proportion to their consumption. Those that drink halfs do not subsidise the Pint drinkers.

I was working on a project that needed to distribute calls in proportions to a number of destinations. These proportions were not simple percentages.

The method being used seemed very clumsy. This method came to me one saturday in the shower. It is very simple and requires no multiples, divides, or lookup tables.

Maplin's Lottery Number Picker kit.

It has a circuit like this:

The switch is connected to A2, and when pressed, A2 is high. The right hand display is turned on by A0 and Left hand display by A1

;
;RA0 - Mux Left.  High to turn on Transistor and display
;RA1 - Mux right.
;RA2 - Switch pulled low by 10K goes high on press.
;
; 	          LED
;	           |
;	         |/
;RA0 ---[ 1K ]---|
;	         |\
;	           |
;	          Vss
;
;
;Take port B high.
;
;Prort B  ----[ 180 ]----LED
;
;    rb3
;rb1     rb2
;    rb0
;rb5     rb4
;    rb6
;


Re chiped:

How it works

Have a number of buckets, one per destination. Fill each bucket in the required proportions. For each call, add the required proportions to each destination's bucket.

The destination for the call is the destination with the fullest bucket.

From the picked destination's bucket, remove the sum of proportions. This keeps the average fill constant.

In the diagram below set P[ i ] for the required proportion. The sum of proportions does not need to add up to 1. For the PIC demo N can be 0 to F

JavaScript Code:

 
function doAnEventLED(){
  var totalWants   = 0
  var totalBuckets = 0
  var maxBucket    = 0   
  var maxBucketCnt = 0
 
  // each output stream has it's own bucket.
  // for each event put a dollop of water equal to the (parts ) portions wanted into each stream's bucket
  for ( var cnt=0; cnt < wantA.length ; cnt++ ){
 
    bucketsA[cnt] -= -wantA[cnt]*1
  
    // work out the totals
    totalWants   += wantA[cnt]*1
    totalBuckets += bucketsA[cnt]*1
 
    //is this bucket the fullest.
    // look for the max, or last equal one.
    if ( bucketsA[cnt] >= maxBucket ) {
      maxBucketCnt = cnt  
      maxBucket = bucketsA[cnt] 
    }
    return  maxBucketCnt  // return destination picked
  }

PIC 16FXX assembler:

;--------------------------------------------------------------------------
; Sec 4.1	Load Share routines - LD
;--------------------------------------------------------------------------
;
; Using the Winner takes all method. 
; For each destination, have a bucket and a corresponding want
;
; For each event add the want to the bucket
; Find out which bucket if fullest, i.e is the largest value.
; This this the destination to be used, so now subtract the sum of the wants from this bucket.
; 
;

	expand

;Define macro
LDloadShareMac macro n

	MOVF	LDwant#v(n),w
	addwf	LDbucket#v(n),f
	
	MOVF	LDbucket#v(n),w
	addwf   LDtotalBucket,f
	
	comf	LDmaxVal,w   
	addwf	LDbucket#v(n),w
	 
	bc		LDloadShare#v(n)
	; New max value
	MOVF	LDbucket#v(n),w
	movwf	LDmaxVal
	movlw	#v(n)
	movwf	LDmaxPtr
LDloadShare#v(n)
endm

LDdoloadShare
	movlw	0x80
	movwf	LDmaxVal
	clrf	LDmaxPtr
	clrf	LDtotalBucket
	
	LDloadShareMac  0
	LDloadShareMac  1
	LDloadShareMac  2
	LDloadShareMac  3
	LDloadShareMac  4
	LDloadShareMac  5
	LDloadShareMac  6
	
	;
	; now knock back the fullest bucket with the total counts.
	;
	bankisel LDwant0

	movlw	LDbucket0
	addwf 	LDmaxPtr,w
	movwf	FSR
	movfw	LDtotalBucket
	subwf	INDF,F
	
    return



LDloadShareInit
	movlw	0
	movwf	LDindex

        clrf	LDmaxPtr
	call	LDclearBuckets

	;
	; Set up the proportions or parts required.
	;

	movlw	8
	movwf	LDwant0
	movlw	8
	movwf	LDwant1
	movlw	8
	movwf	LDwant2
	movlw	8
	movwf	LDwant3
	movlw	8
	movwf	LDwant4
	movlw	8
	movwf	LDwant5
	movlw	8
	movwf	LDwant6
	
	return

LDclearBuckets
    	clrf	LDmaxPtr
    	clrf	LDbucket0
    	clrf	LDbucket1
    	clrf	LDbucket2
    	clrf	LDbucket3
    	clrf	LDbucket4
    	clrf	LDbucket5
    	clrf	LDbucket6
    	clrf	LDbucket7
    
	clrf    LDbucketCarryOsc

	return	

To randomize the sequence if similar proportions are used, add +/- a percentage of Total sum of proportions.

To mop up rounding errors subtract the sum of the bucket fills instead of the required proportions.

It is possible to modify the proportions during use. Proportions of 0 may require checking to prevent spurious picks during startup.

I have used the 7 segment display to show which destination and its proportion N picked on the display.

the kit only had one button so I have used my single button code to allow the proportions to be set.

It is possible to set the proportions using the button

A short press increments through speeds and ePIP / Parallel Osc displays.

A long press enters proportion setting mode. In this mode short presses increment the proportion for the segment.

Another long press moves onto the next segment.

A very long press resets the mode back to the display mode.

Software: PIC code

Software: PIC code hex

A JavaScript demo: demo:

A Parallel oscillator

Using the same buckets use them as an oscillator, and display the most significant bit on the 7 segment display. This produces a pleasing changing display.

The Oscillator drive the left hand display, the carries drive the right hand display.

Conclusion:

This demo shows that the proportion picker can be very simple. It was not immeadiatly obvious how to do this.


Thats enough for now!