AVR Embedded Tutorial - Random: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: AVR Embedded Tutorial - Random
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Random number generator | |
| 2 | + | ||
| 3 | + | A random number generator is not that easy on an AVR. A random(...) function from the System unit is unfortunately not possible. This tutorial shows how to program at least one cube on an AVR. | |
| 4 | + | ||
| 5 | + | The range of the random number must be known from the beginning, for a classic cube this is 6. | |
| 6 | + | ||
| 7 | + | For communication via UART see: [[AVR Embedded Tutorial - UART|UART]]. | |
| 8 | + | ||
| 9 | + | The following methods are suitable for simple random numbers. The prerequisite is that the random numbers are queried at irregular intervals. That is, for example. the case is also the case when a button is pressed which is queried via GPIO. | |
| 10 | + | ||
| 11 | + | This requirement can be seen well in the first example. If you hold down a key in the terminal program, you can easily see a regular pattern. | |
| 12 | + | ||
| 13 | + | If you want a **float** as a random number, it will be very complicated. I haven't found a solution (yet). | |
| 14 | + | ||
| 15 | + | ## A single dice | |
| 16 | + | ||
| 17 | + | ``` pascal | |
| 18 | + | var | |
| 19 | + | Random : byte; // The random number | |
| 20 | + | ||
| 21 | + | procedure Timer0_Interrupt; public name 'TIMER0_OVF_ISR'; interrupt; | |
| 22 | + | const | |
| 23 | + | RandomCount = 6; // Number of dice eyes | |
| 24 | + | begin | |
| 25 | + | Inc(Random); | |
| 26 | + | ||
| 27 | + | if Random >= RandomCount then | |
| 28 | + | begin | |
| 29 | + | Random := 0; | |
| 30 | + | end; | |
| 31 | + | end; | |
| 32 | + | ||
| 33 | + | var | |
| 34 | + | s : ShortString; | |
| 35 | + | begin | |
| 36 | + | // Timer 0 | |
| 37 | + | TCCR0A := %00; // Normal timer | |
| 38 | + | TCCR0B := %001; // Clock = CPU | |
| 39 | + | TIMSK0 := (1 shl TOIE0); // Enable Timer0 interrupt | |
| 40 | + | ||
| 41 | + | // UART | |
| 42 | + | UARTInit; // Initialize UART | |
| 43 | + | ||
| 44 | + | // Enable interrupts | |
| 45 | + | asm | |
| 46 | + | sei | |
| 47 | + | end; | |
| 48 | + | ||
| 49 | + | // Main loop | |
| 50 | + | repeat | |
| 51 | + | UARTReadChar; // Get a keystroke | |
| 52 | + | Str(random + 1 : 4 , s); // Get the random number | |
| 53 | + | UARTSendString(s); // Output random number | |
| 54 | + | until 1 = 2; | |
| 55 | + | end. | |
| 56 | + | ``` | |
| 57 | + | ||
| 58 | + | ## Several dice | |
| 59 | + | ||
| 60 | + | ### Bad solution | |
| 61 | + | ||
| 62 | + | One could get the idea and do the following with several dice: | |
| 63 | + | ||
| 64 | + | ``` pascal | |
| 65 | + | Str(random + 1 : 4 , s); // Get the random number | |
| 66 | + | UARTSendString(s); // Output random number | |
| 67 | + | Str(random + 1 : 4 , s); // Depends on the first letter | |
| 68 | + | ... | |
| 69 | + | ``` | |
| 70 | + | ||
| 71 | + | You get the problem that the order of the throws of the dice is predictable. Therefore this idea is unusable! | |
| 72 | + | ||
| 73 | + | ### Ideal solution | |
| 74 | + | ||
| 75 | + | For this reason I have the following code, because it happens unpredictably. | |
| 76 | + | ||
| 77 | + | The only drawback, it is a bit more complicated, but each random number is independent of the others. In this example there are 15 dice. The timer had to be set a little slower than in the example with only one dice. | |
| 78 | + | ||
| 79 | + | The trick is, not all dice are incremented with every timer call. The second dice only increments with every second call, the third only with the third call, etc. | |
| 80 | + | ||
| 81 | + | ``` pascal | |
| 82 | + | // Global variables. | |
| 83 | + | const | |
| 84 | + | numDice = 15; | |
| 85 | + | var | |
| 86 | + | Random : array[0..numDice - 1] of byte; | |
| 87 | + | ||
| 88 | + | procedure Timer0_Interrupt; public name 'TIMER0_OVF_ISR'; interrupt; | |
| 89 | + | // Local variables | |
| 90 | + | const | |
| 91 | + | RandomCount = 6; // number of dice eyes | |
| 92 | + | var | |
| 93 | + | i : integer; | |
| 94 | + | rnd : array[0..numDice - 1] of byte; | |
| 95 | + | ||
| 96 | + | begin | |
| 97 | + | for i := 0 to numDice - 1 do | |
| 98 | + | begin | |
| 99 | + | Inc(rnd[i]); | |
| 100 | + | ||
| 101 | + | if rnd[i] > i then | |
| 102 | + | begin | |
| 103 | + | rnd[i] := 0; | |
| 104 | + | Inc(Random[i]); | |
| 105 | + | ||
| 106 | + | if Random[i] >= RandomCount then | |
| 107 | + | begin | |
| 108 | + | Random[i] := 0; | |
| 109 | + | end; | |
| 110 | + | end; | |
| 111 | + | end; | |
| 112 | + | end; | |
| 113 | + | ||
| 114 | + | var | |
| 115 | + | s : ShortString; | |
| 116 | + | i : integer; | |
| 117 | + | ||
| 118 | + | begin | |
| 119 | + | // timer 0 | |
| 120 | + | TCCR0A := %00; // Normal timer | |
| 121 | + | TCCR0B := %011; // Clock = CPU / 16 | |
| 122 | + | TIMSK0 := (1 shl TOIE0); // Enable Timer0 interrupt | |
| 123 | + | ||
| 124 | + | // UART | |
| 125 | + | UARTInit; // Initialize UART | |
| 126 | + | ||
| 127 | + | // Enable interrupts | |
| 128 | + | asm | |
| 129 | + | sei | |
| 130 | + | end; | |
| 131 | + | ||
| 132 | + | // Main loop | |
| 133 | + | repeat | |
| 134 | + | UARTReadChar; | |
| 135 | + | ||
| 136 | + | for i := 0 to numDice - 1 do | |
| 137 | + | begin | |
| 138 | + | Str(Random[i] + 1 : 4 , s); // Each dice has its own random number | |
| 139 | + | UARTSendString(s); | |
| 140 | + | end; | |
| 141 | + | ||
| 142 | + | UARTSendString(#13#10); | |
| 143 | + | until 1 = 2; | |
| 144 | + | end. | |
| 145 | + | ``` | |
| 146 | + | ||
| 147 | + | # See also | |
| 148 | + | ||
| 149 | + | - [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview | |
| 150 | + | ||
| 151 | + | --- | |
| 152 | + | *From the Free Pascal wiki, page "AVR Embedded Tutorial - Random", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 153 | + | Category: AVR | |
| 154 | + | Category: Arduino | |
| 155 | + | Category: Embedded | |
| 156 | + | Category: Tutorials |
