Author Topic: Setting an random LED high  (Read 15848 times)

0 Members and 1 Guest are viewing this topic.

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Setting an random LED high
« on: February 07, 2012, 04:56:19 pm »
Hello all,
For a project I need to set an random led high.
So what I would have to do is:
1. create a random number between 0 and 7
2. save that number in a variable
3. light the led
4. save same random number in different variable
5. generate new random number
6. compare old and new random number: if they are equal generate new random number.
run rest of code.

Yesterday in the shoutbox I got pretty far but just barely not there. I do have an random number using rand() but i think it is in binary and between 0b00000000 and 0b11111111 so 0 and 255 decimal. Any idea how to convert it to decimal?  The function doesn't take arguments so the only thing I can come up with is to make the function recursive and let it run until it is within parameters. Timing does not matter. It doesn't have to be completely random. Pseudo random is good enough.

Than there is still the issue of setting and clearing the same led as number in the variable. You cant just use RD num = 1; so how would you do that?

I have something like it running in Python but there you have the great random.randrange() ;D

EDIT: i am using the Hi Tech C compiler
« Last Edit: February 07, 2012, 06:04:49 pm by pelle.jansen »
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #1 on: February 07, 2012, 05:21:13 pm »
How many LEDs do you have? 8?
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #2 on: February 07, 2012, 05:27:38 pm »
How many LEDs do you have? 8?

Yes. 8 LEDs with their appropriate resistors ofcourse.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: Setting an random LED high
« Reply #3 on: February 07, 2012, 05:52:04 pm »
just start with a number, do something to it like multiply and divide it, add or subtract numbers, use a longish number then just use the last decimal digit or do it all in binary and you can just use the last 4 digits, light up the let that corresponds to the number then rerun the computation, you can add in the check that your not using the same number again.

The actual syntax will depend on the language your using
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #4 on: February 07, 2012, 06:11:28 pm »
just start with a number, do something to it like multiply and divide it, add or subtract numbers, use a longish number then just use the last decimal digit or do it all in binary and you can just use the last 4 digits, light up the let that corresponds to the number then rerun the computation, you can add in the check that your not using the same number again.

The actual syntax will depend on the language your using
I use C with the hi tech picc compiler.
Wouldn't that give the same number every time? Or you would have to randomize the calculations you would need something random again. I already have an random number but it is 8 bit binary 00000000 to 11111111. It would be a solution to let just a single bit count or to convert the binary number to decimal.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: Setting an random LED high
« Reply #5 on: February 07, 2012, 06:14:34 pm »
if you start with a large number and do some random calculation on it, and then do the same calculation on the result, and then do the same calculation on the result you will keep getting different numbers, you just need to use the last digit(s)

for example:

start
A = 256
A = A*25/7
B = (last digit)
Led = B
goto start
 

Offline Jad.z

  • Regular Contributor
  • *
  • Posts: 83
  • Country: 00
Re: Setting an random LED high
« Reply #6 on: February 07, 2012, 06:21:29 pm »
Here is a link to a Binary to Decimal conv c code:
http://www.daniweb.com/software-development/c/code/216372
 

Offline 8086

  • Super Contributor
  • ***
  • Posts: 1084
  • Country: gb
    • Circuitology - Electronics Assembly
Re: Setting an random LED high
« Reply #7 on: February 07, 2012, 06:27:30 pm »
To make it random, you can use the ADC (assuming you have one) and read the least significant bits and use them as a seed for your random number generator.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: Setting an random LED high
« Reply #8 on: February 07, 2012, 06:28:39 pm »
what will you supply the ADC with ?
 

Offline 8086

  • Super Contributor
  • ***
  • Posts: 1084
  • Country: gb
    • Circuitology - Electronics Assembly
Re: Setting an random LED high
« Reply #9 on: February 07, 2012, 06:30:49 pm »
what will you supply the ADC with ?

Whatever you like. Nothing. It's just going to be reading noise anyway.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: Setting an random LED high
« Reply #10 on: February 07, 2012, 06:32:43 pm »
thats true, I was wondering where could you get some random noise, maybe just connect an opamp to it and an "aerial" on the opamp input, it can pick up mains hum or anything doing around. remember that micro-controller ADC don't have particularly high input impedences, will they just made noise ?
 

Offline 8086

  • Super Contributor
  • ***
  • Posts: 1084
  • Country: gb
    • Circuitology - Electronics Assembly
Re: Setting an random LED high
« Reply #11 on: February 07, 2012, 06:48:15 pm »
I would expect an on-chip ADC to produce some internal noise even without any input...probably enough to affect the first few LSBs, depending on the resolution. You should get at least one random bit from ADC noise whatever you use, really.
 

Offline SeanB

  • Super Contributor
  • ***
  • Posts: 16284
  • Country: za
Re: Setting an random LED high
« Reply #12 on: February 07, 2012, 07:48:43 pm »
If you are going to use the on board ADC just use 2 resistors to provide it a half supply voltage, and read it as a seed. There will be enough noise on the lower bits if you are using the internal reference and no decoupling cap on the input to the ADC, especially if the chip is not in a low power mode at the time. Then take the random number output and AND it with 00000111 binary, to mask out a value between 0 and 7 dec. Then you can either use a table to drive the outputs or use any other method as you now have a random number with 8 variations.
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #13 on: February 07, 2012, 08:07:55 pm »
You can convert it to decimal in software, but then you have to divide by 32. You must utilise the full range of the random number generated by the rand function, otherwise sometimes no LEDs will be on.

Here is a lightweight solution without multiplications and divisions. You can do a simple set of if/elseif statements. You might need to change this to compile under HITECH C. The idea is to decimate the number into ranges.

unsigned char var;  //declare

var = rand (); //initialise by generating a random number 0...255.

if ((var>=0)  && (var<=31)) light_led(1);
elseif ((var>=32)  && (var<=63)) light_led(2);
elseif ((var>=64)  && (var<=95)) light_led(3);
.....
elseif ((var>=223)  && (var<=255)) light_led(8);

Even if you get the logic a bit wrong, only 1 led will light up because of the elseif statement.

Simples!

EDIT: Sean, the method in your last post above will not work, it only samples regions inside the dynamic range of the random variable. Most of the times the bitwise operation it will return 0. For example, if the random number is 8 in decimal i.e. 0x00001000, then 0x00001000 & 0x00000111 = 0x00000000 i.e. 0.
 

Offline Jad.z

  • Regular Contributor
  • *
  • Posts: 83
  • Country: 00
Re: Setting an random LED high
« Reply #14 on: February 07, 2012, 08:21:09 pm »
What you people are suggestingis a bit too much for his simple application.
You are suggesting to use white noise, to generate a completely random number, for someone who clearly stated that pseudo random is good enough. And lets not forget that the range he needs is 0 to 7 now how random that have to be ::)
Plus he is a beginner who have just started experimenting with PICs and flashing some LEDs; i don't think ADC come next, not yet.
« Last Edit: February 07, 2012, 08:24:01 pm by Jad.z »
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #15 on: February 07, 2012, 08:58:23 pm »
I could also use the timer. The PIC16F877A i am using has 3 build in timer modules. All of them are still free but I seem to be unable to set the OPTION_REG register to set the timer options. I get the error "conflicting declarations for variable "OPTION_REG"(/Microchip/Hi_Tech_C_MIDRANGE/include/pic16f877a.h:639). When I go to that line in question it is the volatile unsigned char OPTION REG @0c081. Now I am not that familiar with .h files but it looks fine. Otherwise would it be a good idea to just let the timer run at a low speed, reset when it reaches 7 and read the timer when needed? That might work. Otherwise counting pulses from an external 555 timer ic should also do the trick. By reading the value and resetting when it reaches 7 it should give me an random number. It is just a little fun prototype so it doesn't has to be perfect.

@Jad.z You can learn a lot in 3 weeks. About a month ago I barely knew what a microcontroller was. Now I at least master digital IO and know how to use other things. Like timers. When the option register is not giving you an headache :-\.
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11891
  • Country: us
Re: Setting an random LED high
« Reply #16 on: February 07, 2012, 09:39:56 pm »
I do have an random number using rand() but i think it is in binary and between 0b00000000 and 0b11111111 so 0 and 255 decimal. Any idea how to convert it to decimal?

I think you have a bit of a misunderstanding here, perhaps. As far as a computer is concerned a number is a number. The number "5" for example is the same number in binary or in decimal (or in hex or in octal). It is only the representation on paper that changes, not the size of the number. So there is no need to convert to decimal. You just calculate with the number as an integer--for example, add and subtract, multiply and divide as required.
 

Offline PedroDiogo

  • Regular Contributor
  • *
  • Posts: 62
  • Country: pt
  • EE Student
Re: Setting an random LED high
« Reply #17 on: February 07, 2012, 10:10:50 pm »
Hello all,
For a project I need to set an random led high.
So what I would have to do is:
1. create a random number between 0 and 7
2. save that number in a variable
3. light the led
4. save same random number in different variable
5. generate new random number
6. compare old and new random number: if they are equal generate new random number.
run rest of code.

Yesterday in the shoutbox I got pretty far but just barely not there. I do have an random number using rand() but i think it is in binary and between 0b00000000 and 0b11111111 so 0 and 255 decimal. Any idea how to convert it to decimal?  The function doesn't take arguments so the only thing I can come up with is to make the function recursive and let it run until it is within parameters. Timing does not matter. It doesn't have to be completely random. Pseudo random is good enough.

Than there is still the issue of setting and clearing the same led as number in the variable. You cant just use RD num = 1; so how would you do that?

I have something like it running in Python but there you have the great random.randrange() ;D

EDIT: i am using the Hi Tech C compiler


I suggest you pick the 3 LSB (as you only need to light 8 LEDs) from the output of the rand() function and convert it to decimal.

I can see a simple way to convert it to decimal:

Code: [Select]
#define BIT(word, n) ((word >> n) & 1)
#define randToDecimal(word) BIT(word,0) + BIT(word,1)*2 + BIT(word,2)*4

void main ()
{
int randomNumber = rand();
printf("Random number: %d\n", randomNumber);
printf("3 LSB to decimal:%d\n",randToDecimal(randomNumber));
}

And then use the result to light up the appropriate LED.
However you could use the rand() output to directly light a random number of LEDs each time, without converting it to decimal.
 

Offline Jad.z

  • Regular Contributor
  • *
  • Posts: 83
  • Country: 00
Re: Setting an random LED high
« Reply #18 on: February 07, 2012, 10:12:06 pm »
Actually I once read a code that generate a random number by counting the bounces of a tactile switch.

A bit off topic, but here is an application note on switch bounce:
http://pdfserv.maxim-ic.com/en/an/AN287.pdf

And here is an example on debouncing using software:
http://www.secondvalleysoftware.com/hardware/io/pdfs/softDebounce.pdf

Extra one (I know you can't speak assembly, but you can read the description of the steps  :P)
http://members.ee.net/brey/Debounce.PDF
 

Offline senso

  • Frequent Contributor
  • **
  • Posts: 951
  • Country: pt
    • My AVR tutorials
Re: Setting an random LED high
« Reply #19 on: February 08, 2012, 12:54:20 am »
There is also the shift solution.
int i = rand() % 8;
PORTA = 1<<i;

And its done.
 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: 00
Re: Setting an random LED high
« Reply #20 on: February 08, 2012, 01:26:30 am »
Since you're just playing around, Senso's code is all you probably need.  The C function rand() returns a pseudo-random number of so many bits.  (Consult your compiler documentation.)  You then use the C modulus operator like Senso shows in his example to turn the number rand() returns into a number between, in your case, 0 and 7.

The problem with rand() is that every time you power-up or reset, the numbers it generates will be the same as last time.  If you're worried about that then read up on the srand() function.  This provides a 'seed' for the pseudo-random number generator.  Where do you get a good seed?  Read the Wikipedia page for "Hardware random number generator."  You basically need a white noise source such as a thermistor or avalanche diode.  You might be able to utilize a timer and/or even some sort of user interaction to seed the generator as well. 

You need to seed the generator only once after power-on/reset.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9951
  • Country: nz
Re: Setting an random LED high
« Reply #21 on: February 08, 2012, 01:45:30 am »
id probably just program an array of random numbers into the micros eeprom and step through the array index jumping in steps derived from the value obtained and values either side of it.
But to avoid the exact values at startup you'd need to periodically store the current random value in eeprom and use that to seed the system at startup.
« Last Edit: February 08, 2012, 01:53:04 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: 00
Re: Setting an random LED high
« Reply #22 on: February 08, 2012, 02:31:15 am »
I guess the funny thing about randomness, at least on microcontrollers, is that it isn't simple.  You can get a good seed on a PC just by using the timer.  (As in the date and time, how many seconds the PC has been running, etc.)  You generally don't have this luxury on a MCU.

It's not terribly satisfying to see your program do the exact same thing each time you power it up when it is supposedly doing something 'at random.'  LOL.

Some MCU have built-in temperature sensors.  The lower-order bits of that sensor is another source of 'random' bits for your seed.
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #23 on: February 08, 2012, 10:13:15 am »
I think it is very simple:

Code: [Select]
unsigned char Value=0, oldValue=0 ;

for (;;)
{
   Value = rand() & 0x07 ; // mask all most significant bits except the 3 LSB:
                           // 'Value' is between 0 and 7
   if (Value != OldValue)
      {
      OldValue = Value ;
      // light the 'nth' LED using the number (0-7) stored in 'Value'
      }
 }
If you need a seed for your random generator, the suggestion to use the Least Significant Bits (LSB) of an ADC channel is a good one.
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #24 on: February 08, 2012, 04:29:56 pm »
I think it is very simple:

Code: [Select]
unsigned char Value=0, oldValue=0 ;

for (;;)
{
   Value = rand() & 0x07 ; // mask all most significant bits except the 3 LSB:
                           // 'Value' is between 0 and 7
   if (Value != OldValue)
      {
      OldValue = Value ;
      // light the 'nth' LED using the number (0-7) stored in 'Value'
      }
 }
If you need a seed for your random generator, the suggestion to use the Least Significant Bits (LSB) of an ADC channel is a good one.
This workes like a charm! Does just what I need it to do. Thanks for the input all.
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #25 on: February 08, 2012, 05:40:39 pm »
Does it? Lets test it. Say the rand funtion returns 16. What value will be stored in value and which led will light up?
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #26 on: February 09, 2012, 12:49:12 am »
Does it? Lets test it. Say the rand funtion returns 16. What value will be stored in value and which led will light up?
Really simple:
16 = 00010000 in binary
ANDing the 0x07 mask to 16 results:
00010000 AND 00000111 = 00000000
so the result is 0

The 0x07 mask sets to 0 the most significant bits of your number:
00000xxx
Only the bit marked with 'x' will remain untouched.
The operation is the same as follows:

Value = rand() % 8 ;

but using the '&' operator (AND) is faster and (to me) more readable
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #27 on: February 09, 2012, 12:54:23 am »
Does it? Lets test it. Say the rand funtion returns 16. What value will be stored in value and which led will light up?
Really simple:
16 = 00010000 in binary
ANDing the 0x07 mask to 16 results:
00010000 AND 00000111 = 00000000
so the result is 0

The 0x07 mask sets to 0 the most significant bits of your number:
00000xxx
Only the bit marked with 'x' will remain untouched.
The operation is the same as follows:

Value = rand() % 8 ;

but using the '&' operator (AND) is faster and (to me) more readable

...and thats why no LED (or only the first LED) will light up for generated numbers that do not have any of the three LSBs set. Thats a lot of numbers.
« Last Edit: February 09, 2012, 12:56:03 am by Alex »
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11891
  • Country: us
Re: Setting an random LED high
« Reply #28 on: February 09, 2012, 01:02:01 am »
...and thats why no LED (or only the first LED) will light up for generated numbers that do not have any of the three LSBs set. Thats a lot of numbers.

I don't get that. There are 8 LEDs and 8 values, 0 - 7.

0 => LED #1,
1 => LED #2,
2 => LED #3,
...,
7 => LED #8.
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #29 on: February 09, 2012, 01:33:26 am »
...and thats why no LED (or only the first LED) will light up for generated numbers that do not have any of the three LSBs set. Thats a lot of numbers.

I don't get that. There are 8 LEDs and 8 values, 0 - 7.

0 => LED #1,
1 => LED #2,
2 => LED #3,
...,
7 => LED #8.

If the OP just copies the number stored in 'value' to the LED port then only 3 of the LEDs will light up, LED 1-3. A binary to decimal decoder will have to be implemented. Thats one issue.

The other issue is that a portion of the dynamic range of the random number generated is being utilised. If the binary representation of the number generated by the rand function does not contain any 1 in the 3 LSBs then the masked value will be 0. In other words, you are not scaling the random number to fit 8 LEDs, you are truncating it.
 

Offline senso

  • Frequent Contributor
  • **
  • Posts: 951
  • Country: pt
    • My AVR tutorials
Re: Setting an random LED high
« Reply #30 on: February 09, 2012, 02:27:02 am »
Yes, I never use the % in my micro-controllers code, only in pic32 that as hardware modulus and so its as fast as doing it or the &, but I was typing with one hand because I was freezing with cold, and I wanted to pass the idea to the OP, there are lots of options to choose from.
One way to get some random seeds is to read an analog channel, and you probably can make it more random if you read it 16 times and only store the first(bit 0) of each reading and then make a 16 bits value out of it.
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11891
  • Country: us
Re: Setting an random LED high
« Reply #31 on: February 09, 2012, 02:35:07 am »
If the OP just copies the number stored in 'value' to the LED port then only 3 of the LEDs will light up, LED 1-3. A binary to decimal decoder will have to be implemented. Thats one issue.

What "LED port"? What makes you think the OP is going to do something that won't work? You have constructed a straw man argument based on an imaginary hypothesis in order to knock it down. I think you should give the OP more credit, especially since this:

This workes like a charm!

I mean, if the OP has tested it and found it working, why do you think it only lights 3 LEDs?

The other issue is that a portion of the dynamic range of the random number generated is being utilised. If the binary representation of the number generated by the rand function does not contain any 1 in the 3 LSBs then the masked value will be 0. In other words, you are not scaling the random number to fit 8 LEDs, you are truncating it.

Here you do have a point. Taking the lowest few bits of a random number will reduce the randomness significantly. But for the purposes of this exercise it was accepted higher up the thread that perfection was not required. Nevertheless, it is as well to be aware of the limitations of the algorithm chosen.
 

Alex

  • Guest
Re: Setting an random LED high
« Reply #32 on: February 09, 2012, 03:21:02 am »
Ian, we have to work with fragmented info here. Regarding ports, the op mentioned 8 leds with resistors. Thats a typical reply of a number of leds connected to an output port of the mcu. Pelle, how have you connected your leds? The connection method is important as it links with the code.

About the 3 leds. The op quoted a block of code that doesnt do bcd conversion. As you say the op says it works, so there is a conversion taking place at some point. That should be mentioned.Maybe if i had used past tense it would be even more clear what i meant, which is the scenario thay no conversion is used.

Thats all there is to the above points.

I am glad you understood what i meant about the range of the number. This piece of info is crucial if what you want is equal probability for all leds.
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11891
  • Country: us
Re: Setting an random LED high
« Reply #33 on: February 09, 2012, 03:49:22 am »
My interpretation is that the MCU has eight of its pins designated as outputs. Each pin is connected to an LED via a current limiting resistor. Set the output high to turn on the LED, set the output low to turn off the LED.

The above code was posted:

Code: [Select]
unsigned char Value=0, oldValue=0 ;

for (;;)
{
   Value = rand() & 0x07 ; // mask all most significant bits except the 3 LSB:
                           // 'Value' is between 0 and 7
   if (Value != OldValue)
      {
      OldValue = Value ;
      // light the 'nth' LED using the number (0-7) stored in 'Value'
      }
 }

It all depends what code lies behind "light the 'nth' LED using the number (0-7) stored in 'Value'". This comment tells me the intent is clearly understood, but we don't have sight of the actual code. Maybe there is a pair of functions like this:

Code: [Select]
unsigned char Value=0, oldValue=0 ;

for (;;)
{
   Value = rand() & 0x07 ; // mask all most significant bits except the 3 LSB:
                           // 'Value' is between 0 and 7
   if (Value != OldValue)
      {
      OldValue = Value ;
      clear_LED(OldValue);
      light_LED(Value);
      }
 }

I won't try to write these functions; they could be written using a switch() statement, or more simply by indexing the output pins off of Value. Something like "set_pin(base+value);" even. (Where set_pin(index) sets the state of the indexed output pin to high.)
 

Offline l4rtt-1

  • Contributor
  • Posts: 11
Re: Setting an random LED high
« Reply #34 on: February 09, 2012, 08:56:00 am »
I won't try to write these functions; they could be written using a switch() statement, or more simply by indexing the output pins off of Value. Something like "set_pin(base+value);" even. (Where set_pin(index) sets the state of the indexed output pin to high.)

Or just as simple as:

PORTX = 1 << Value;
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #35 on: February 10, 2012, 11:41:18 am »
Hi all
First I want to thank you all for your input! :D
I did get it working with the srand() reading an input from the analog channel which is floating. There is only one thing: I had to use 8(!) if statements to get it to work. It works but is very ugly of course. Every way I try to solve it it doesn't work. Some tips would me much appreciated!

Code: [Select]
/******************************************************
 * Pelle Jansen
 * 5 - 2 - 2012
 *
 * Sets a random LED high, LED can be cleared by pressing corresponding button.
 *
 * PIC16F877A
 *
 * X1: 8 MHZ, 2 22 pF capacitors to ground
 * Code is still ugly as shit, please bear with me.
 * ****************************************************
 */

#include <htc.h> // main PIC header file
#include <stdlib.h> // Reqired for randomize() and rand()
#include "delay.h" // for DelayUs()
#include "delay.c" // for some reason necessary for DelayMs()


/* External high speed 8 MHZ crystal oscillator, Watchdog timer disabled
 * brouwn out reset enabled, EEPROM protection disabled
 * write protect disabled, code protect disable, Low voltage programming disabled
 * power on timer enabled.
 */
__CONFIG(FOSC_HS & WDTE_OFF & BOREN_ON & CPD_OFF & WRT_OFF & CP_OFF & LVP_OFF & PWRTE_ON);

/*system*/
#define XTAL_FREQ 8 MHZ

/*functions*/
int rando(){
    int value;
    value = rand() & 0x07;
    return value;
}

/*main function*/
void main (void)
{
    TRISD=0x00; // PORTD as output
    TRISB=0xff; // PORTB as input

    ADCON1 = 0b00010000;
    ADCON0 = 0b00000001;
    DelayUs(1);
    GO_DONE = 1;
    while (GO_DONE)
        ;
    srand(ADRESH);

    int randval, oldval, out;
    randval=rando();

    while (1) // infinite loop
    {

      if (randval != oldval){
          PORTD = 1 << randval;

          if (RB0 == 0){
              out=0;
          }         
          else if (RB1 == 0){
              out=1;
          }
          else if (RB2 == 0){
              out=2;
          }
          else if (RB3 == 0){
              out=3;
          }
          else if (RB4 == 0){
              out=4;
          }
          else if (RB5 == 0){
              out=5;
          }
          else if (RB6 == 0){
              out=6;
          }
          else if (RB7 == 0){
              out=7;
          }

          if (out==randval){
              randval=rando();
              oldval=randval;
          }

          else{
              continue;
          }
         
      }
      else{
          randval=rando();
      }

    }
}

Analog inputs were a lot easier than I thought. A good read trough the datasheet gave me everything I needed.
« Last Edit: February 10, 2012, 01:27:21 pm by pelle.jansen »
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #36 on: February 10, 2012, 01:06:25 pm »
1) it is more than 15 years I'm not using PICs, so I hope I remember correctly the I/O port syntax...
2) I modified the code without trying to compile it, so maybe there are some errors in it
3) You never mentioned you was checking an input port (PORTB) and required to read its status: I hope to understand there can be a bit set to 0 and you have to identify it...
4) i removed your 'rando()' function because you need to call it only 1 time...

Code: [Select]
void main (void)
{
    TRISD=0x00; // PORTD as output
    TRISB=0xff; // PORTB as input

    ADCON1 = 0b00010000;
    ADCON0 = 0b00000001;
    DelayUs(1);
    GO_DONE = 1;
    while (GO_DONE)
        ;
    srand(ADRESH);

    unsigned char randval=0, oldval=0, out, i; // they are UNSIGNED CHAR!!!!
    randval=rando();

    while (1) // infinite loop
        {
      randval = rnd() & 0x07 ; // only values from 0 to 7
       
        if (randval != oldval)
            {
            // assign value to the 'old' variable
            oldval = randval ;
            // light the 'n'th led
            PORTD = 1 << randval ;
           
            // scan the 8 input ports
            // 'out' is set to 0xFF to avoid undefined cases
            for (out=0xFF, i=0 ; i<8 ; i++)
                {
                // check if input port 'i' is set to '0'
                // the loop will be exited at the first occurrence of '0' on PORTB
                // be careful! if every bit of PORTB is set to '1', 'out' value is UNDEFINED!!!
                if (!(PORTB & (0x01 << i)))
                    {
                    out = i ;    // set 'out' to number of port found to 0
                    break ;      // exit from the loop: I have found a bit set to 0
                    }
                }
            }
      }
}

[added some hours later]
Corrected the code to use Bitwise AND operator (&), instead of Logical AND operator (&&)
« Last Edit: February 10, 2012, 04:06:55 pm by eliocor »
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #37 on: February 10, 2012, 02:04:16 pm »
1) it is more than 15 years I'm not using PICs, so I hope I remember correctly the I/O port syntax...
2) I modified the code without trying to compile it, so maybe there are some errors in it
3) You never mentioned you was checking an input port (PORTB) and required to read its status: I hope to understand there can be a bit set to 0 and you have to identify it...
4) i removed your 'rando()' function because you need to call it only 1 time...

1. 15 years is a long time :o. What do you use now?
2. There were some errors but they were easy to correct.
3. I thought it would be relatively easy. Just reading a input and writing it in a variable sounds soo simple but it isn't.
4. Actually 2 times  ::)

But... it doesnt work. Your for loop seems to always return 8 (all leds light if you assign it to PORTD). Here is the modified code:
Code: [Select]
/******************************************************
 * Pelle Jansen
 * 5 - 2 - 2012
 *
 * PIC16F877A
 *
 *Sets a random LED high, LED can be cleared by pressing corresponding button.
 *
 * X1: 8 MHZ, 2 22 pF capacitors to ground
 *
 * ****************************************************
 */

#include <htc.h> // main PIC header file
#include <stdlib.h> // Reqired for randomize() and rand()
//#include "delay.h" // for DelayUs()
#include "delay.c" // for some reason necessary for DelayMs()


/* External high speed 8 MHZ crystal oscillator, Watchdog timer disabled
 * brown out reset enabled, EEPROM protection disabled
 * write protect disabled, code protect disable, Low voltage programming disabled
 * power on timer enabled.
 */
__CONFIG(FOSC_HS & WDTE_OFF & BOREN_ON & CPD_OFF & WRT_OFF & CP_OFF & LVP_OFF & PWRTE_ON);

/*system*/
#define XTAL_FREQ 8 MHZ


/*main function*/
void main (void)
{
    TRISD=0x00; // PORTD as output
    TRISB=0xff; // PORTB as input

    ADCON1 = 0b00010000;
    ADCON0 = 0b00000001;
    DelayUs(5);
    GO_DONE = 1;
    while (GO_DONE)
        ;
    srand(ADRESH);

    unsigned char randval=0, oldval=0, out, i;
   
    randval = rand() & 0x07; //

    while (1) // infinite loop
    {

      if (randval != oldval){
          PORTD = 1 << randval;

          for (out=0xFF, i=0 ; i<8 ; i++){
            // check if input port 'i' is set to '0'
            // the loop will be exited at the first occurrence of '0' on PORTB
            // be careful! if every bit of PORTB is set to '1', 'out' value is UNDEFINED!!!
            if (!(PORTB && (0x01 << i)))
                {
                out = i;    // set 'out' to number of port found to 0
                break;      // exit from the loop: I have found a bit set to 0
                }
            }

          if (out==randval){
              oldval=randval;
              randval= rand() & 0x07;
             
          }
      }
     
      else
          continue; // is this necessary?

    }
}
I am still pretty unfamiliar with the &, &&, | etc operators. That happens when you get spoiled by learning a high level language first  ::)
« Last Edit: February 10, 2012, 02:27:09 pm by pelle.jansen »
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #38 on: February 10, 2012, 02:22:58 pm »
1) mostly Freescale and Arm (NXP/ST)

2)what is the use of your reading on PORTB: please can you explain it?

3) same for this piece of code:
if (out==randval){
  oldval=randval;
  randval= rand() & 0x07;
  }

It is really not clear (to me) what you want to do...

I have the slight impression there is something 'cheesy'....
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #39 on: February 10, 2012, 02:28:26 pm »
It is stated in the comment on top of code.
 *Sets a random LED high, LED can be cleared by pressing corresponding button.
It is part of a little fun reaction time game.
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #40 on: February 10, 2012, 02:37:26 pm »
BTW, I wrote the wrong operator:
instead of '&&' (logical AND)
you have to put the '&' (bit AND):

if (!(PORTB & (0x01 << i)))
in such way it will exit when it will find the FIRST 0 (counting from B0 to B7).

Sorry for the inconvenience (it was written in a hurry)
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #41 on: February 10, 2012, 02:46:14 pm »
BTW, I wrote the wrong operator:
instead of '&&' (logical AND)
you have to put the '&' (bit AND):

if (!(PORTB & (0x01 << i)))
in such way it will exit when it will find the FIRST 0 (counting from B0 to B7).

Sorry for the inconvenience (it was written in a hurry)

Yup, that did it  ;D

No problem. It just proves that yore human :D Only thing was that I tried for like 15 minutes before thinking it won't work.
Can you give me some clarification about those operators? I am totally unfamiliar with them and my C tutorial doesn't cover it for some reason.

Thanks for your input! 8)
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #42 on: February 10, 2012, 02:53:54 pm »
Or not.
The PIC seems to freeze after a sort while   :-\
What could cause this?
 

Offline eliocor

  • Supporter
  • ****
  • Posts: 519
  • Country: it
    • rhodiatoce
Re: Setting an random LED high
« Reply #43 on: February 10, 2012, 03:03:28 pm »
No idea about the freezing, but I do not think it depends on the code...

regarding the Bitwise operations, please take a look at the following links:
http://en.wikipedia.org/wiki/Bitwise_operation
http://en.wikipedia.org/wiki/Bitwise_operations_in_C
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #44 on: February 10, 2012, 04:35:35 pm »
Thanks, I will definitely read through that article!
Now up to solving that darn freeze problem >:(
 

Offline pelle.jansenTopic starter

  • Contributor
  • Posts: 24
  • Country: nl
    • Check out my Youtube channel!
Re: Setting an random LED high
« Reply #45 on: February 10, 2012, 08:56:30 pm »
Hi all,
I rebooted my Mac, unplugged and replugged my PicKit 3 and TADA it worked ::). Some strange glitch in the compiler or MPLAB X I guess. Well for all of you interested, here is the final code. Fully annotated so everyone will understand what I am trying to do.
Code: [Select]
/*******************************************************************************
 * Pelle Jansen                                                                *
 * 10 - 2 - 2012                                                               *
 * V1.1                                                                        *
 * Free to distribute, use, modify, whatever you like ;)                       *
 *                                                                             *
 * Designed for PIC16F877A                                                     *
 *                                                                             *
 * Reaction time game                                                          *
 * Sets a random LED high, LED can be cleared by pressing corresponding button.*
 *                                                                             *
 * X1: 8 MHZ, 2 22 pF capacitors to ground                                     *
 * RA0: for random number. LEAVE FLOATING!                                     *
 * Entire PORTB: 8 switches to ground with external Pull up resistors          *
 * Entire PORTD: 8 LEDs with corresponding resistors                           *
 *                                                                             *
 ******************************************************************************/

#include <htc.h> // main PIC header file
#include <stdlib.h> // Reqired for randomize() and rand()
#include "delay.c" // for some reason necessary for DelayMs()

/* External high speed 8 MHZ crystal oscillator, Watchdog timer disabled
 * brouwn out reset enabled, EEPROM protection disabled
 * write protect disabled, code protect disable, Low voltage programming disabled
 * power on timer enabled.
 */
__CONFIG(FOSC_HS & WDTE_OFF & BOREN_ON & CPD_OFF & WRT_OFF & CP_OFF & LVP_OFF & PWRTE_ON); // config bits

/*Defenitions. Defines, global variables funcions etc*/
/*system*/
#define XTAL_FREQ 8 MHZ /*required for DelayUs() and DelayMs()*/
/*user*/
// add user defenitons
/*macro's*/
//add user macro's

/*main function*/
void main (void)
{
    /*Digital initilization*/
    TRISD=0x00; // PORTD as output
    TRISB=0xff; // PORTB as input

    /*Analog initilization*/
    ADCON1 = 0b00010000; // set analog config registers
    ADCON0 = 0b00000001;
    DelayUs(20); // wait for analog channel 0 to get a reading
    GO_DONE = 1;
    while (GO_DONE)// wait for reading to complete
        ;
    srand(ADRESH); // seed the random analog input value to the rand() function
    /*Local variable defenition*/
    unsigned char randval, oldval=0, out, i; // variable definiton
    /*initilization*/
    randval = rand() & 0x07; // get initial random number between 0 and 7
    /*Main infinite loop*/
    while (1)
    {
        if (randval != oldval){ // make sure the number is not the same as the last one
            PORTD = 1 << randval; // set the value on LEDs shiftet one to the left

          for (out=0xFF, i=0 ; i<8 ; i++){ // check each for 0 the loop will be exited at the first occurrence of '0' on PORTB
            // be careful! if every bit of PORTB is set to '1', 'out' value is UNDEFINED!!!
            if (!(PORTB & (0x01 << i))){
                    out = i;    // set 'out' to number of port found to 0
                    break;      // exit from the loop: I have found a bit set to 0
                }
          }
          if (out==randval){ // if the random number is equal to the number gotten from the buttons
              oldval=randval; // set the oldval variable to the current (old) random number
              randval= rand() & 0x07; // generate new random number between 0 and 7
        }
        else{ // if the random value equals to the old random value
            oldval=randval; // set the oldval variable to the current (old) random number
            randval= rand() & 0x07; // generate new random number between 0 and 7
        }
        }
    }

}

Thanks all for your support. Couldn't have done it without your support guys! 8)
« Last Edit: February 13, 2012, 01:16:08 pm by pelle.jansen »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf