Lucky Wheel

Abracadabra Lucky Wheel

Pekka Ritamaki



Normally electronics projects show some device, which is useful for you. This project tells how you can make a useful electronic device for others, especially for children: Electronic Lucky Wheel.
I will tell first what were my design goals and how I make my first prototype. Then I will explain the processor selection and how the device should work. The power supply and user controls are explained next. An IR-remote control was added on parallel of the start button. I will also explain the program code with high-level c-language. Assembly skills are not needed. Most of published electronics projects include the embedded processor, but the software part is hardy mentioned. In this project the software is the most important functions and it is declared in detail.

This project is presented with pictures, drawings, schematic diagrams, a part lists, a pcb-layout rather than with many words. I know how young people read electronics projects.
All the parts are normal plated though devices. The project can easily duplicated in the schools with help of the teacher even with 12-15 year old children. The young painters can design their own front plate or look my two designs.

Here is the source code

Project:     Acrabadra Lycky Wheel
Name :         Pekka Ritamaki
File :        g:\pic\pic2007\roulette\reoulette.c
Date :         10.10.2007 
CPU  :         PIC16F628A-I/P, internal osc 4MHz, DIP18  
Compiler:      CCS/PCM  
Output:     Roulette.hex for PICKIT2 programmer  
Power :     4-5V 20mA 
Function :     32 leds connected to matrix, start button ( RA.4 to ground( or Ir reciers starts timer 

Dimensions 800*1200 mm bottom 18 mm 
32 pcs  5 mm yellow superbright leds  Kingsbright L62, circle radius 360 mm  70 mm distance 
Power  6V 4AH rechargeable battery  Panasonc LC-RB064P or 4*1.5 V AA batteries
Cherging through 47R ohmin resistor diode in series from 12V DC plug 

Power on :
- roulette runs fast 6.5 sec
  move normal sound and led operation 13.5 - 26 secs
- slows and sound alos slows by a buzzer
- the winning light is on for  30 secs
- start attraction movement slowly 1 sec intervall
- wait IR or Button 

Harware PIC16F628
regulator 78L05

LED Cathodes  to  8 pins in PORTB, LED anadeds to  PORTA.0 PORTA.1 PORTA.2 PORTA.3 
Pin 15 of PIC  drives buzzer transisistor through 1 k resitor, which goes the base of NPN BC547 for buzzer 


#include <16F628.H>

#use delay(clock=4000000,restart_wdt)
#use fast_io(A)
#use fast_io(B)

        (C) Copyright 2007 PROBYTE Pekka Ritamaki, Tampere, Finland 
// register constants  
#byte INTCON = 0xB
#byte PORTA = 5
#byte PORTB = 6
#bit  G1  = PORTA.0
#bit  G2  = PORTA.1
#bit  G3  = PORTA.2
#bit  G4  = PORTA.3
#bit  BUTTON = PORTA.4
#define ON 0
#define OFF 1
// variables 
unsigned int16 blinkspeed,  // delay ms between leds  starts  from 1 ms to 1000 ms at finish 
     endCounter,          //  how many leds are moved during the fast run, 
                       // random number is taken from timer1 at time of start button + added offset time   
     waitTimer;        //   30 sec timer before the attractiom mode , start after fast run 
unsigned int8 rowGroup, // PORTA LED anode groups  4 rows: RA.0, RA.1, RA.2 nad RA.3 
    ColumnCathode;  //  PORTB LED cathodes 8 bit in PORTB 

// 1 KHz sound is made with timer1 , 4MHz/4/8 -> 8us pulses to 16 bit timercounter 
// Timer1 Reload  0x10000 - 500us/8u  => 65474 = 0xFFC2
int1     SoundOn,      // buzzer timer 
    FastModeOn,     // normal fast rotation  
     Blink;         //
// functions, first Interrupt functions

//========================== ISR ================================   
// Timer1 Interrupt routine 
void timer1_isr( void) {
    set_timer1( 0xFFC2);  // 0.5ms reload generates  2*0.5ms = 1 kHz sound 
    if( SoundOn )

/*============================ ISR =========================
 timer0 interrupt is genaral timing rounties
 timer overload in  65,5 ms periods    4MHz/4/256 -> 256us pulses ,  256us * 256 counter => 65536 us 
 Timer0 bliks the leds in fast mode 
 and decrease the endcounter, which contorols the stopping of the led rotation 
 waitTimer is started after the fast roulette run is stopped. 
 When the fast timer is ended, slow attraction run is started 

==================Timer0 ISR=======================*/
void clock_isr(void) {
// if fast blink is on, Blink PORTB  ( = cathode of the leds) on and off 15 times / sec
    if(Blink)  {
           set_tris_b(0xff); // port direction register set to inputs, leds off  
           Blink=0;          // Blink variable 
      } else
         set_tris_b(0);              // port direction register set to output, leds on
restart_wdt(); // keep watchdog on 

if( endCounter)
  endCounter--;  // end counter stops the final rotation
if(  waitTimer)
     waitTimer--;  //When roulette has stopped, waitTimer is started. 
                 //  After he 30 s waittime the roulette start slow movement

// ===========Normal functions ===================================  

// LED Blinking delay function,  speed decrease at the end fast run 
void delay( void) {
long i;
for ( i=0; i<blinkspeed; i++)

// ========== Init the PIC hardware, timers m inteeruopt, port direction registers  
void init_hardware ( void) {
  PEIE=1;          // enabe interrupt register      
  port_b_pullups (true);  // B-port pullups on 
  setup_counters( RTCC_INTERNAL, RTCC_DIV_256); //divide timer0 by extra 256  to 65 ms overload in timer0 
  setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8 );    //  divide timer1 by 8 to get 1kHz sound with buzzer
  enable_interrupts(INT_RTCC);                  // enable timer0 interrupt              
  enable_interrupts(INT_TIMER1);                 // enable timer1 interrupt 
  enable_interrupts(GLOBAL);                     // enable global interrupt
  set_tris_b( 0x0);                            // All bits in PORT B to output mode for the leds   
  set_tris_a( 0b110000);                     // set Port A  direction registers. has four led row anodes RA.0- RA.3 and one start button RA.4   
  PORTB=0xFE;  // First LED on 
  PORTA= 0x1;  // First Anode row RA.0 on set to 5 V


//Wait button pressed every 10ms total 1 second for slow movement
BYTE WaitDelay( void) {
 BYTE i;
  for ( i=0; i<100; i++) {
     if(!BUTTON) return 1;
  return 0;
// Move leds slowly  in attraction mode 
void waitMovement(void) {
 BYTE i,j, rounds;
 while (1)
    for ( i=0; i<4; i++)  // move the rows 
     PORTA= rowGroup;
     set_tris_a ((~rowGroup) & 0x3F); //set only one row for output
      for (j=0; j<8; j++)           // move the columns 
            PORTB = ~ColumnCathode;  // only one column catode on at timei
                    return;      // if button presed stop the waitng mode 
            ColumnCathode = ColumnCathode <<1; // move colums to next column ( LED cathodes)
        if(!ColumnCathode)            // overflow start again 
               ColumnCathode=1;      // from column 1 
      }               // for j end
     rowGroup = rowGroup <<1;     // move the groups
     rowGroup &= 0xf;             // mask groups to lower nibble
     if (!rowGroup)
      rowGroup=1;           // start rows again ?
    }             // for j end
 }   // while (1)  end 

// Sound off 
void SetSoundsOn (void) {

// Sound on 
void SetSoundsOff (void) {

// move the leds fast and blink the led at first part of wheel toration 
// =================================
void FastMovement ( void) {
BYTE i,j, rounds;


while(1) {
   blinkspeed ++;
   for ( i=0; i<5; i++)  // move 4 groups one at time 
   {  // rotate groups
      PORTA= rowGroup;
     set_tris_a ((~rowGroup) & 0x3F); // only on row group is outtput
      for (j=0; j<8; j++)  // move 8 cathodes of the led to 0V one at time  
            PORTB = ~ColumnCathode;  // set cathode of the one led to 0V, others to 1 
             if( endCounter < 100)   
                    blinkspeed +=50;
           delay_us(10);  // 10 us delay between steps 
             if(!endCounter)   // the roulette has ended, stop the sound 
            ColumnCathode = ColumnCathode <<1; // move one cathode of 8 Led columns to upper bit 
            if(!ColumnCathode)          // if all the colums done start from the biginning ( PORTB.0) 
               ColumnCathode=1;         // Firs column catode to 0V
     rowGroup = rowGroup <<1;     // move prsent Led row to next Led row
     rowGroup &= 0xf;          //Mask rows to low nibble (1,2,4,8) 
     if (!rowGroup)    
       rowGroup=1;           // if rows has done, start from first row again 

 Normal fast led movement and make sounds
 increse the 
 EndCounter = how many led movents is displayded in the fast run 
void rotateMakeSounds( void) {
BYTE i,j,x;

rowGroup=1;  // start from row1 
ColumnCathode=1;    // start colunmCathode 1 

SetSoundsOn();  // set sounds on 
blinkspeed=1; // start as fast mode 

while(1) {    // do forever or until the end counter gotos to 0 
  blinkspeed ++;

for ( i=0; i<4; i++){  // rotate four rows 

  PORTA= rowGroup;
  x=(~rowGroup) & 0x3F;      // define PORTA tris register bits 
  set_tris_a (x);         //  set tris bits, one for output at time  
  for (j=0; j<8; j++)        // rotate columns 
     x= ~ColumnCathode;        // invert the column bit 1,2,4,8,0x10,0x20,0x40,0x80 to 0xFE, =0xFC .. 
    PORTB = x;             // set right  ColumnCathode to  0V  other bits to one 

     if(!BUTTON )
       {                  // if IR receiver get pulse during fast rotation  slow the counter timer 
         if( endCounter > 50)        // limit the endcounter ie. make stopping faster,  brake the rotation 
             endCounter -= 50;       // but not to excatly end 
        if( endCounter < 150)       // if the rotation is still at further from end 
            blinkspeed +=25;        // increase time between led counter 
         if( endCounter < 100)
            blinkspeed +=25;
         if(blinkspeed & 63) SoundOn =!SoundOn;
    ColumnCathode = ColumnCathode <<1;
    if(!ColumnCathode) ColumnCathode=1;
   }  // For j end 
 rowGroup = rowGroup <<1;  // rotate ROWS up  
 rowGroup &= 0xf;           // mask the rows to low nibble
 if (!rowGroup)
    rowGroup=1;   // o start frob row 1 again 
}  // For i end 
}  // while (1) end 

// set starting values to variaables 
void InitVariables ( void) {
    waitTimer= 76;    //  76* 65 ms = 5 sec 
    endCounter &= 0x1f;  // 6.5 sec from the end 
    delay_ms(get_timer0());   // random delay     
    FastModeOn=1;            // fast blink mode
     FastMovement();        // start the roulette makeing first fast round  
     FastModeOn=0;            //    
     set_tris_b(0);  // port B mode to output     
     endCounter = endCounter+ (get_timer1()&0xff) ;
     waitTimer= 225;     // 15 secs 

/************** Main ****************************
 - init hardware
 forever loop : 
 - three modes:
    30 sec wait timer  
    attraction  mode
    fastrun mode  from the IR and start button  
void main(void) {

init_hardware ();
InitVariables (); 


   while(BUTTON &&  (waitTimer > 0)) ;   // wait here to show last result led for 5 second 
      waitMovement(); // slow attraction movent is stopeed immediately if button or IR comes on 
      endCounter = 15;  //1 sec =  15* 65 ms   fast rotate mode 
      FastModeOn=1;      // fast blinking mode 
      FastMovement();  // fast normal rotation, blink the led for 1 second, but  so sound 
      FastModeOn=0;    // random number from Timer1 lobyte 
      endCounter = (get_timer1()&0xff) +200; // 200 *65 ms = 13 sec mininum and 26 sec maximun rotation 
      rotateMakeSounds();  // normal fast rotation 
      waitTimer= 458; // 30 secs wait utnit next attraction slow movement

} // end main module roulette.c  //

Here is the hex-file

A pcb-board can be made available to make a project easy to build.

Design goal

The children's winter festival organised by charity clubs needs every year a new attraction device. I thought it might be possible to build such using modern components. I thought a design goal:
• It must be a familiar Tivoli device, but based to electronics.
• One person can easily move it to athletic field with a car.
• It must work 2-3 hours without external power supply.
• It must stand in snow without external support.
• It must give a user a feel of controlling of luck.
• It must give results in numbers, which show small prizes according to the results in the table near by.
• It must be easily built of a normal materials found in home in one weekend.

Mechanical work

With this list in my mind, I looked my garage and found a broken children's bed. It will be converted to free standing electronic Lucky Wheel. I made a 1200*800*50 mm box with battens strips and plywood. I cut the wooden sidelines of the bed to half to make a tripod by three rods to support the roulette box like a painter’s stand.
Using a 360mm string, I draw a roulette circle by a pencil in the middle of front plate. Then I drilled 32 holes for 5mm leds spaced evenly with a distance of 70 mm. The yellow super bright leds were connected to matrix of 4*8 and wired to 20-pin flat cable from old hard disk cable. I used a hot glue to fix leds and strands to the background. The ICD20 connector goes to a small, perforated PCB board. It has the brains in CPU and power regulator. The power regulator is not absolutely necessary. PIC16F628 works with 6V.


Operating principles

To make an electronic roulette work I needed a processor. The smallest suitable for controlling 12 IO was an 18 pin PIC16F628. A matrix of 32 leds needs 12 I/O-pins. A start button and a sound buzzer take two pins. Normally Microchip 18-pin devices has maximum of 13 I/O-pins. This part has however an internal oscillator, which saves two pins and one pin was left over. When roulette starts the leds rotates and blink fast. It seems that every led is on all the time. Actually leds are multiplexed one at the time.
The sound buzzer gives an audio feedback and a feel of a real roulette. After a while the roulette slows down and sound starts clicking like in a real roulette. A list of numbers shows which prize categories. The numbers are intended to show the prizes in the table near the wheel. A child can then select a prize from his winning class. Normally some prizes are more popular than others. This double indirect method enables the operator of the Lucky Wheel sort or change prizes during the show.


IR remote control and the rotating of the leds

For the charger connector and the start button I drilled two 10 mm holes and then expanded part of holes to 20 mm with cone drill. The big holes protect mains switch and button during transportation. Because it was a little difficult to press the start button, I added a remote control in parallel of the start switch to middle of the led board. Any IR-remote receiver works with this IR-detector. Because now I have a possibility to control the roulette, I added a feature how the user can brake the roulette. By pushing his lucky number, actually any number, he or she can control the lucky wheel. The leds stop more rapidly, but the result is still a random operation. After 30 second from stopping, the roulette starts an attraction mode, i.e. it slowly moves leds on the circle. The labels on the display are painted on random sequence red and black number, so a real roulette operation is also possible.

Generating a random number


The random number is based as fast free running 16-bit Timer1 in the microprocessor. It gives a seed number for down counter at the moment when the user press a start button. The leds are displayed by in the sequence based to this counter. Although the leds are rotating in the sequence the numbers are shown random in the front plate, because they are not painted in sequence.
If user breaks the rotation by a remote control, the led end counter is decreased, but not at very last part. 50 led moments can't be controlled. The user has no opportunity to control the final round. Timer 0 controls the blinking of all the leds. So the leds are rotating very fast at first, blinking and sound ticks change the pitch according the rotation speed.
The microprocessor circuit is the simplest one; there is no crystal, not even one series resistors for 32 led. The internal circuit of PIC CPU limits the current of IO-pins to 20-25 mA, which is just suitable for leds.

Power supply

I used 6V 4Ah battery and 7805 regulator to power the roulette. It works more than a week of continuous work without charging. Four Zinc-carbon batteries and rechargeable NiCd batteries works as well. The power regulator uses a standard LM7805 regulator, which may be more easily available than smaller TO-92 can LM78L05. The low voltage drop in some regulators, like LM2931, is better for 6 volts, but it is not easily found in local electronics shops. Also it has some nasty behaviour.

The total current is 20mA even all the lights seems to works at time. A charger indication led shows if the charger is right polarity and it is working. In the field a car cigarette lighter with long wire to DC plug work as a charger.


A source and hex codes are provided for the Lucky Wheel.

After 40 years of programming I have invented a standard software style for embedded processors: Tampere style. If the programmer follows a standard programming practice, a working source code is easy to make each time. These are the rules applied for Microchip range of microprocessors:

1. Make list of each used pins and choose them so that they do not interfere others.
2. Record the I/O directions for each pin
3. Make a list of the usage of all the timers and interrupts
4. Select a clock oscillator value and make a list of the fuses to this cpu.
5. Draw a rough sketch of the operations of a main loop and interrupts
6. Define the data structures for common variables. Use structures even if they are not needed. Structures help to understand the usage of the variables.
7. Write the hardware initialise function. Set the direction registers, set the timers, also the timers which is not used. Enable interrupts, PWM, SPI, I2C, UART even if they are not used. Clear all the variables.
8. Read the eeprom-setup to variables, if needed.
9. Write the interrupt stubs, even you do not know exactly the interrupt code.
10. Write the main loop as selection case style
11. Use ON-LINE programming
12. Test the code with some means of the debugging with short interval. Serial communication is the best method, even if it not used in the final application. Some leds or sound output help debugging. Without easy debugging, the programming will last forever.
13. Develop output and input functions at first. These functions are helpful at developing the rest of the code.
14. Check the timing of counters with oscilloscope and led(s).
15. Make continuous backups from the working, but not ready, programs for the later reference.
16. Use old good but different programs as a base of the new program
17. Use descriptive camel-style programming names for variables. In camel style variables are separated by uppercase letters like unsigned int8 MainOperationMode.
18. Define all the variables as signed or unsigned and int1, int8, int16 , int32 or float.
Look the flow diagram of the Lucky Wheel and the source code.
The program starts with three definition rows for the compiler CCS/PCW version 3.x .

#include <16F628.H>
#use delay(clock=4000000,restart_wdt)

These three lines define a PIC16F628A cpu with 4MHz internal oscillator, watchdog used, Power on timer delay, no low voltage programming enabled. The reset pin is not used for the reset but for the IO-function although it is not used in this application.

init_hardware() function sets the hardware of the cpu.

Timer1 prescaler is set to 8:1. Timer1 interrupt works with 0.5 ms intervals to get 1kHz sound to small speaker. Timer0 prescaler is set to 256. Timer0 interrupt generate timing with 65.536 ms intervals.
All the bits in direction registers of PORTB is set as outputs. PORTA has on input. The four low bits of the PORTA is set as outputs.
The main program has thee modes: wait, attraction and fast run mode. In wait state WaitCounter is counted down by timer1 in 65 ms periods


Timer1 interrupt toggle the sound bit if the sound is required. The sound information is controlled by a SoundOn bit-variable. At each interrupt the Timer1 is set to suitable reload value to get 2*500us square wave. A Timer1(0xFFC2) command sets the 16-bit timer to 50 counts ( 65536-50=0xFFC2) before overflow.
Timer0 interrupt in fast mode blinks the leds connecting the port direction registers to output and input in 65 ms interval. This gives more interesting effect to rotating leds. This interrupt also decrease the EndCounter-varible. This variable determines the fast rotating leds. The EndCounter starts from random value, which is got from the Timer1 at time of start of the fast operation. The routine in Timer0 decreses the WaitTimer variable at the waiting mode. 5 second WaitTimer is 76 65 ms interrupts.


The main loop

After the rest the wheel makes one fast rotation. Then program waits the start button or signal from the IR-receiver. After five seconds the WaitCounter variable is counter to Zero. Slow WaitMovement()- function starts moving the leds forward in attraction mode. The one second delay between slow movements is divided to 100 pieces of 10us delays in WaitDelay( )- function. If the start-signal is found, this function returns 1 and as fast operation starts.

FastMovement()- function starts rotating the leds, blinks the leds for one second without sound .
After this one second an EndCounter value is read from Timer1. This variable controls the rotation count. The minimum and maximum values are limited with following sentence.
endCounter = (get_timer1()&0xff) +200; // 200 *65 ms =13 s-26 s

The SoundOn-bit is set to control the sound at Timer1 interrupt. The EndCounter decreases with BlinkSpeed variable after each led movement.
Only one led in matrix is lit each time. This is done first selecting one rowbit in PORTA and then selecting one columnbit in PORTB. The eye of the human shows many leds rotating all the time.

Breaking the wheel

The user get feel of control of operation by pushing the remote control. He or she is told to use his lucky number, but really any IR-button has a same effect, it decreases the EndCounter and increases BlinkSpeed variables. The rotations stops faster and the delay between the leds is shorter in delay() function. The braking if the last 50 led movement is prevented from user. The sound is switched on and off between led movements to get additional effects.


The final result

When the EndCounter is zero the leds stop rotating and show on final result. Although the leds rotate in sequence the numbers in front plate is random. The result can be ODD or EVEN numbers, SMALL or BIG NUMBER, RED or Back. Zero do not belong ODD or EVEN categories. The operator wins every time. If the user has selected his or hers lucky number and lucky number is got, the price is still the same. If someone wins bigger price is not good practice. After 5 second the leds starts moving slowly as an attraction mode. It is similar to normal fast mode, but there is no sound and the IR-start do not make break, but starts fast mode.


The experience from real usage

The experience from local children festival was a success. During two hours time in front of a new gadget has a row of eager users from 5 to 15 years old. The younger children operated the wheel helped by their mothers or the operator. The operation costs one euro and the winners got choice of prices: a drawing book, a set of candies or a bar of chocolate.
The net result to charity was 100 euros. The charge in batteries lasted. The sound in the crown can be bigger and light in the leds could be brighter in direct sunlight.
The wheel was easy to carry with one person from handle. It fits inside my station wagon. At first time I used a three-leg strand for the wheel, but later I just put wheel leaning to car. The lucky wheel can be used in school bazaars to attract the younger people and their parents. In birthday parties this can be a highlight for younger children.



A new electronic device is described. It is easy to build and it has also useful functions. The device is the most simple in hardware, complicated in software.
It can be built even without PCB-board as I did it in my first prototype. The price of the component depends the price of the super bright leds. I used yellow 2500 mcd leds. New 9000 mcd leds can be found for 0.5e a piece. A new pack of four NiCd 2.5Ah batteries costs 4 euros. PIC16F628-I/P costs about the same. Wooden parts costs about 10 euros. The total component price is around 30 euros without wood and plywood.

Abracadabra: an old broken bed was transformed to a new kind of moneymaking device in a weekend.


Word Files:

Electronic_Roulette.doc a Word document
Electronic_Roulette.pdf, a Adobe Acrobat file

List of drawings
Fig 1 Luckywheel.jpg a front plate a front plate of Abracadabra Lucky Wheel
Fig 2 rouletteschema.cdr Abracadabra Lucky Wheel schematic diagrams
Fig 1 Rouletteframe.cdr a CorelDraw 9.0 file

Fig 3 roulettepower.cdr a CorelDraw 9.0 file A power supply of the Lucky Wheel
Fig 2 rouletteschema.cdr a CorelDraw 9.0 file A schematic diagram of the Lucky Wheel
Figure 4 Ready made Abracadabra Lucky Wheel
Fig 5. Luckywheelwork.jpg A picture of the Lucky wheel in a winter festival
Fig 6. Lykywheel_in_work.jpg
Fig 7. RouletteCodediagram.crd a flow diagram of the Lucky Wheel
Program Files :
Roulett.c a c-language source code
Roulette.hex A PIC16F628 HEX-program

Lycky WHEEL electronic parts list
by Pekka Ritamaki moc.liamg|odg3ho#moc.liamg|odg3ho

Comment Pattern Quantity Components

Capacitor 0.1uF 50V AXIAL 5mm 2 C1, C2
Resistor 0.25W 10R AXIAL 0.4" 1 R4
Resistor 0.25W 10k AXIAL0.4 1 R9
Resistor 0.25W 1k Axial 0.4" 2 R2,R3
Resistor 0.25W 47R Axial 1." 1 R1
CPU 16F628-I/P DIP18 1 IC2
Socket 18pin DIP18 1 IC2
Diode 1N4007 Axial 0.5" 1 D1
Diode 1N4148 Axial 0.4" 1 D2
Pin header 20PIN IDC20 1 X1
Regulator 5V LM7805 TO-220 1 IC1
Transistor BC547 TO-92 1 Q1
Conncetor IDC20 1 X1
Cable 1m flat cable 20-pin 1 X1
Switch SPST Power 1
Pushbutton SP 1
Charger DC-plug 2.5mm 1
Batterypack 6V 4Ah or battery pack 4*1.5V size AA
IR receiver SFR4138 1
Superbright led 5mm yellow 32
PCB lyckywheel.pcb 1
Program for CPU luckywheel.hex 1

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License