PDA

View Full Version : help with random pause times; PIC16f88



woodpickle
- 27th April 2014, 08:20
I'm working on a school project, and this is the first time the course has been taught at my small university. Naturally, the professor is from the Apollo age, and the TA isn't too much help.

Using a PIC16F88, I want to make a simple program that illuminates an LED and displays a count from 0-9 on a small 7 segment LED display that increases each time the LED flashes. I have the ability to write this type of code, but my main goal is to insert a pause in between the LED lighting up and the counter increasing. I want this pause to be random, and if the pause duration is <= say, 900, the program goes to a Sub that prompts the user to manually reset the program and begin again.

I have been able to somewhat get an idea of how to generate a random byte using the resources on the forum already.

Something like...

MyWord var Word
MyByte var Byte


Random MyWord
MyByte=(MyWord//9)+1



pause (Mybyte * 100)


If (Mybyte == 9) Then
GoTo errorloop
Endif

Is this type of math operation allowed when using pause?

Amoque
- 27th April 2014, 13:07
I believe you can. I was unable to (quickly) find an example to verify, but it should not take but a moment to try it.

I think that one of the reasons I was unable to find an example is that long pauses are often avoided because the processor does nothing during a pause but spin a tight, uninterruptable, loop. Most often pauses are kept short purposely, during longer waits other constructs or functions are used to fill the time - such as NAP or SLEEP - that put the processor into low power mode.

Consider: Pause 10000. For approximately 10 seconds nothing happens. Any display is not updated, any serial communications fail, no user input will be serviced, and no interrupts are processed. All that is going on is that the processor is burning thru (battery most significantly) power without any other purpose but to wait.

Now:

For LP0 = 0 to 9 'Loop 10 times (Loop 10 times (Loop 10 times))
For LP1 = 0 to 9 'Loop 10 times (Loop 10 times)
For LP2 = 0 to 9 'Loop 10 times
Pause 10 'Pause 10
Next LP2
Next LP1
Next LP0

In this example the processor pauses an equivalent time, but interrupts can be serviced (between the much shorter pauses) and, by inserting code inside the outer loops, buttons can be checked, displays updated...

Typically, when there is truly nothing for the processor to do, delays are managed with functions that put the processor "to sleep" so as to save power. In your case, this has the added benefit that these functions are not particularly accurate - thus adding a random element to their timing.

One last...
For no particular reason, you may consider a construct to make a loop of a known duration, then call the loop a random number of times, as:

Main:
Toggle LED
For RandomDuration = 0 to (RandomNumber between 1 and 10)
Gosub PauseTime
Next RandomDuration
Goto Main

PauseTime:
For LP1 = 0 to 9
For LP2 = 0 to 9
Pause 100
Next LP2
Next LP1
Return

The only advantage I see in this scheme is that the random waits will be (likely) clearly different in duration between one and the next, where straight random pauses may vary by hundreds or even thousands of cycles and not be noticeably different in duration to the user.

HTH,
Another Buzz Aldrin

woodpickle
- 27th April 2014, 19:40
Ah! Does that mean I was on the "right" track with my original idea? Although it does sound very inefficient. I'm just looking for something simple that works on a breadboard and power supply situation, as we have a limited time to do the project.. unfortunately.

I liked your second example and it got me thinking...

Would it be better (in my case) to have loops; say, 0-9, each loop contains a different pause duration between lighting the LED and updating the display, I would have the main loop call a random number 0-9, which would go to each loop.

Let's see if I can mock it up...

MyWord var Word
MyByte var Byte

mainloop:

Random MyWord
MyByte=(MyWord//9)+1

If (MyByte == 1) Then
GoTo loop1
EndIf
If (MyByte == 2) Then
GoTo loop2
EndIf
If (Mybyte == 3) Then
GoTo loop3

;this continues to MyByte == 9

If (MyByte == 9) Then
GoTo errorloop ;error loop displays "E" on the LED display and waits for the user to press the reset button
Return

loop1:
High led1
pause 100
GoSub updatepins ;updates the display with the count, (not included yet in example)
Low led1


the loops would increase in pause duration of course. I hope I am on the right track here. I still have a couple days to complete this, but aside from one introduction to C# class, this is the first time I've had any experience with coding.

Amoque
- 28th April 2014, 15:51
In every project there are a myriad ways to accomplish the goal. If what you conceive meets your goal and is within your skill level - I count that as success! I'd say, yes... you were on track.

The purpose of the "PauseTime" subroutine is to demonstrate how a long pause may be achieved without paralyzing the processor for undue lengths of time. It is FUNCTIONALLY equivalent to Pause 10000. It is not "better" in your case, only offers advantage when other processes require service.

First priority is to complete your assignment on time - do that using the method you understand best; I have no wish to derail your train of thought, only to explain why long pauses are not well illustrated by random example. I really enjoy the opportunity to payback some of the help I have received here, but I don't wish to influence your design decisions. Ask whatever you like, I'll (and many others likely) will try and help, but please don't let me be a distraction to your instructor's curriculum.

That said, my approach would be to write a subroutine that provides a simple pause of a minimum acceptable length then, call the routine multiple times to provide a random factor, except in the case of "9" where you branch to the error handling routine.

Main:
Generate random number

If number is 9 goto Errorhandler 'If our random number is 9 GOTO where we deal with it

This part only happens when our random is NOT 9

Display the random number

For Delay = 1 to Random number ' Use the variable Delay as a counter from 1 to our random number.
gosub delay 'Go find our pause
Next Delay 'If Delay < our random number, +1 to Delay then go back and pause again

Goto Main 'do it all over



Delay:
pause 1000 'this is the shortest pause, we'll do this once if our random number was 1, three times if it was 3....
Return 'go back to the line after the gosub

ErrorHandler:
Here's where we do whatever we want to happen when 9 is the random number
Dispay an "E"....

Goto Main: 'Go back to "Main", generate a new random number and start over

Do you follow the logic here? The Main loop picks a number, if that number is nine, it leaves the loop for Errorhandler to handle the special case. Otherwise, it displays the number before the "For Delay" loop pauses 1 second "RandomNumber" times. Goto Main starts the process again. What the user will see: A random number, then a pause of equal number of seconds, another random number will appear and another pause of equal seconds... If a nine is our random number, an "E" appears and whatever else you code in errorhandler. Once the errorhandle coder is completed another number is generated, appears on the display, and the pause begins.

Demon
- 28th April 2014, 16:43
Good ideas, but as stated, make it so it fulfills your needs.

If your mcu does nothing else, PAUSE with a random number works. If your project will evolve, then it might be worth the effort to implement the ideas above.

I'd go for simple, a random number between 1 and 9, multiply by 200. This gives a range of .2 - 1.8 seconds.

Robert