And..
Bruce is using PM for an assembler in that example.
And..
Bruce is using PM for an assembler in that example.
Dave
Always wear safety glasses while programming.
Thanks for that Walter.
Hi mackrackit,
Tonight's silly question: What's PM? Is that a Microchip assembler?
Dave
PM is the assembler from the Pic Basic folks. It works well on the older and smaller chips.
MPASM from MicroChip works for everything.
Dave
Always wear safety glasses while programming.
So a program written in PBPro would compile and run using the MPLAB IDE?MPASM from MicroChip works for everything.
Or am I North of the North pole.....again?
Dave
You are still some what south...
MPLAB or MCS will work. So will a simple text editor. For writing code that is. I find myself using gEdit or EMACS more often than not.
Once the code is written the compiler/assembler can then be ran.
Do you remember *.bat files??
Dave
Always wear safety glasses while programming.
Yes, Batch files, small text file program commands... cmd.exe.Do you remember *.bat files??
Here is the guts of a BAT
It is just the command line stuff that the manual talks about. It is really nice having the command line option for PBP.Code:cd cd C:\MAC\PIC_PROGS\PPPBP\test_prog\ PBPL -e -ampasmwin -p18F4550 test.bas cd\
Dave
Always wear safety glasses while programming.
Hi mackrackit,
I had a read of the manual dinner time today (right at the beginning).
So what we're saying here is that you can use most text editors to write the code and then 'invoke' the compiler to then create the HEX file and away you go.
Dave
Yes.
I do like text editors with syntax highlighting but even windows notepad will work. If I remember correctly that is what Melanie uses, just plain 'ol notepad.
Dave
Always wear safety glasses while programming.
Goes to show then...........If I remember correctly that is what Melanie uses, just plain 'ol notepad.
Dave
Ah, almost forgot, the Badger re-appeared last night I'm very pleased to say.
Below is a part of a simple little program I've been experimenting with to generate a 'random' pause but of known maximum and minimum time period(average maximum wait about 12secs for the LED to flash as the program stands).
The pause occurs randomly but because there are a maximum of 65535 'lenghts' if you will of a given time (be it clock cycles etc (I'm not sure how RANDOM works) it should be possible to my mind to work out how long the longest and shortest pause times will be when they occur (1 or 65535 lenghts) I think.
So my question is this: How long does it take the PIC processor to calculate 1 lenght? At the moment the maximum and minimum pause times occur at 12secs max 1sec min.
I hope this makes sense
DaveCode:X VAR WORD main: RANDOM x PAUSE X /4 HIGH PORTA.2 PAUSE 1000 low PORTA.2 GOTO MAIN:
Last edited by LEDave; - 8th July 2010 at 00:22.
Can you setup a LCD or have the value of x sent to a terminal? I would think you should have at times a longer pause than 12 seconds??
You may want to look at this also.
http://www.picbasic.co.uk/forum/showthread.php?t=9350
Dave
Always wear safety glasses while programming.
Hi mackrackit,
I've been working really hard on this. I've taken your idea of:
And done this:Can you setup a LCD or have the value of x sent to a terminal?
What I've done is change the original code to measure the time the LED is on rather than measure the time the program was 'PAUSED' because to my mind you can only use 'PULSIN' on a active pin. I've then tried to output that 'PULSIN' number using 'SEROUT2' to the Serial communicator.
It nearly works I think, what it does is output a series of zeros, instead of the time in micro_secs. I suspect I've made an error here:
I think it could be the Decimal value of Z that's causing the problem (I hope) being as it should be measuring in blocks of Micro_secs.Code:SEROUT2 PORTC.3, 16780, [DEC Z, 10 ,13] 'The measured RANDOM time sent to S/Communicator
Here's the program, I feel I'm close, but am I?. If you could look the program over and give me a pointer that would be really appreciated. The chip is a 16F684.
DaveCode:ANSEL = %00000000 'Disable analog select so ports work as digital i/o. CMCON0 = %00000111 'Disable analog comparators. TRISA = %00000000 'Set PORTA as OUTPUT. PORTA = %00000000 'Set PORTA pins all low. TRISC = %00000000 'Set PORTC as OUTPUT. PORTC = %00000000 'Set PORTC pins all low. DEFINE OSC 4 X VAR WORD 'Number between 1 & 65535 Y var WORD 'Scaled down value of X Z VAR BYTE 'The PAUSED value of Y in 10us Increments main: RANDOM X 'Random number between 1 & 65535 LET Y = (x /14) 'Scaled down value of X HIGH PORTA.2 'LED PORTA.2 lights up PAUSE Y 'LED on for time period of RAN_X_OVER_14 PULSIN PORTA.2,1,Z 'The paused RANDOM time period stored in VAR Z SEROUT2 PORTC.3, 16780, [DEC Z, 10 ,13] 'The measured RANDOM time sent to S/Communicator 'in 10us incremets low PORTA.2 'LED off GOTO MAIN: 'Do it all again
Last edited by LEDave; - 8th July 2010 at 21:47.
Ah, have I got 'PULSIN' in the right place in the program? Might it be better in front of HIGH PORTA.2 ?
Nope, still outputting zero's.
The manual says of zero's:
Now I'm thinking the pulse must happen because the LED lights and with a 'RANDOM' delay but could it be to big to measure?If the pulse edge never happens or the width of the pulse is too great to measure, Var is set to zero
How big is too big to measure for a pulse?
Dave
Last edited by LEDave; - 8th July 2010 at 23:20.
As far as I know PULSIN is for reading a pulse on a pin from the outside not a pulse from the inside.
It has been a long day so maybe I am missing something... What exactly are you wanting to do?
Dave
Always wear safety glasses while programming.
Hi Dave,
I see you've been making a lot of progress, good job!
Remember that PBP executes one statement at the time. In this case you set the pin high, then you pause, then you start the pulsein statement which waits for a positive going signal which isn't coming since the pin is already set high so it times out and returns zero.
On top of that, as Mackrackit says, PULSIN is meant to be used on pins configured as inputs, I'm not sure if it works like you have it.
And, why do you need to measure it? Why not simply "print" the value returned by the RANDOM command? I mean PAUSE works with units of ms if RANDOM returns 100 you divide that by 14 and get 7 so you'll get a pause of 7ms, if RANDOM returns 34567 you divide that by 14 and you'll get 2469ms pause. I don't see the point in trying to measure that but if you really need to do that then look into using one of the PICs hardware timers. Reset it, set the pin high and start the timer. Pause x, set the pin low, stop the timer and read its value.
/Henrik.
Hi Henrik,
Sorry for the late reply.
That'll be down to mackrackit, yourself and a few others, thanks for sticking with me, it's very much appreciated.I see you've been making a lot of progress, good job!
I was running the program through my mind as I was going of to sleep last night and realisedRemember that PBP executes one statement at the time. In this case you set the pin high, then you pause, then you start the pulsein statement which waits for a positive going signal which isn't coming since the pin is already set high so it times out and returns zero.
just that.
Another mistake, I got the PULSIN idea into my mind and rushed to write some code and overlooked setting the the REGISTER pin to INPUT.Good practice would be to set the I/O REGISTER then start writing code, I'll try and stick with that from now on.On top of that, as Mackrackit says, PULSIN is meant to be used on pins configured as inputs, I'm not sure if it works like you have it.
Another gap in my knowledge base I'm afraid, I didn't know you could 'print' the value.And, why do you need to measure it? Why not simply "print" the value returned by the RANDOM command?
Spot on Henrik, just what I needed to know.PAUSE works with units of ms if RANDOM returns 100 you divide that by 14 and get 7 so you'll get a pause of 7ms, if RANDOM returns 34567 you divide that by 14 and you'll get 2469ms pause.
I'm trying to write a program for a project which must have a RANDOM delay of zero to three seconds.
So how about this:
65535 / 21.845 gives 3000ms as a Maximum value. Any number generated will be lower than 65535 therefore shorter than 3 seconds!
DaveCode:ANSEL = %00000000 'Disable analog select so ports work as digital i/o. CMCON0 = %00000111 'Disable analog comparators. TRISA = %00000000 'Set PORTA as OUTPUT. PORTA = %00000000 'Set PORTA pins all low. TRISC = %00000000 'Set PORTC as OUTPUT. PORTC = %00000000 'Set PORTC pins all low. DEFINE OSC 4 X VAR WORD 'Number between 1 & 65535 Y var WORD 'Scaled down value of X Z VAR BYTE 'The PAUSED value in 10us Increments main: RANDOM X 'Random number between 1 & 65535 LET Y = (x /22) 'Scaled down value of X PAUSE Y 'LED on for time period of RAN_X_OVER_22 HIGH PORTA.2 'LED PORTA.2 lights up PAUSE 500 low PORTA.2 'LED off GOTO MAIN: 'Do it all again
Last edited by LEDave; - 9th July 2010 at 13:33.
Another quick question:
I've rounded up the Value 21.845 to 22 see below
When I used the value of 21.845 and try and compile it I get an error saying bad variable modifier. Is there any way of making the program use 21.845 for super accuracy?Code:LET Y = (x /22) 'Scaled down value of X
Dave
Hi Dave,
Sure, the value returned by Random is just as any other variable stored in WORD size variable.Another gap in my knowledge base I'm afraid, I didn't know you could 'print' the value
That should work. Obviously you'd have to change Pause 500 to Pause Y. Another small note, there's really no need for the Y variable in this case, it's perfectly OK to do:I remember reading that RANDOM in reality is far from that. Being given a certain seed it returns the same "random" number, in the same order every time the program is run, or something like that. Search the forum a bit and I believe you'll find some info regarding that.Code:TRISA.2 = 0 Random X SEROUT 2 PORTC.3, 16780, [DEC X, 13, 10] 'Send value out X = X / 22 'Scale down, no need for the Y variable. PortA.2 = 1 Pause X PortA.2 = 0
/Henrik.
http://www.picbasic.co.uk/forum/show...ht=random+seed
An MCU does not handle anything other than integer math with out some heavy manipulation. Most times it is better to find away around using decimals. So in your case I would stick with 21.
Or you could dive into this
http://melabs.com/resources/fp.htm
Dave
Always wear safety glasses while programming.
Hi Dave,
I missed that second post of yours but Mackrackit covered it. The PIC only deals with integer numbers but there are several tricks around that, here's one:As you can see here, the X = X*1000 most likely produces a result that won't fit within a WORD, however PBP (even before the arival of LONG variable) allows you to use the intermediate 32bit result for calculations like this one. So, we multiply X by 1000 and then divide it by 1000*21.845 which is the same as dividing X by 21.845 in the first place. It will truncate whatever is to the right of the decimal point but in this case it means that you'll be off by no more than 1ms.Code:X VAR WORD Random X X = X * 1000 X = DIV32 21845 SEROUT2, PORTC.3, 16780, [DEC Y, 13, 10]
Thanks Mackrackit for digging up the posts on RANDOM!
/Henrik.
Last edited by HenrikOlsson; - 9th July 2010 at 14:22.
Too clever by half you two......
No seriously great stuff and a great help. Henrik thanks for code, looks just the ticket.
So RANDOM isn't really RANDOM, only a pseudo RANDOM. Which gives me another small problem. I don't want the 'seed' to start in the same place when the PIC is powered up and run.
Is there a way of starting the 'RANDOM' cycle with a different 'seed' at power_up each time?
Dave
Hi Dave,
I was sure you could specify the "seed" but a look in the manual shows I was wrong :-( Anyway, it would only "offset" you into the predermined list of "random" numbers as explained in the thread Mackrackit linked to. There are a couple of ideas in that thread bu I don't currently have any good advice regarding that.
There's a small typo in the example code in my previous message but I'm sure you spotted that.
/Henrik.
If you want to play with the hardware...
Have a momentary start push button that triggers a mosfet to start the PIC. When the PIC starts a pin will keep the mosfet triggered. To kill the PIC another momentary push button will break the gate signal to the mosfet.
WHILE
the start push button his held "down" to start the PIC it also brings another pin HIGH.
RANDOM X
WEND
GOTO MAIN PROG
Kinda sounds like something Goldberg would do
Dave
Always wear safety glasses while programming.
Where to start?
Hi Henrik, at first glance, should that be:There's a small typo in the example code in my previous message but I'm sure you spotted that.
?Code:[DEC X, 13, 10] instead of Y
Hi mackrackit, who's Goldberg? The hardware idea looks interesting, something to think about there.Kinda sounds like something Goldberg would do
I've just ran the RANDOM / 22 SEROUT2 through the serial communicator with a 1 second pause between outputs so I read the values, absolutely brilliant to see, highest value I read was 2977 milli_secs so pretty good. I'll run Henriks a little later tonight when I get a minute.
Brilliant stuff this,thanks again.
Dave
I'm truly amazed tonight
I've managed to get Henriks DIV32 program to run and the accuracy is absolutely spot on! And I mean absolutely spot on!
I wanted a program that could PAUSE randomly within a period of 1ms to 3000ms.
Here's part of the code:
To test it I ran it through the Serial Communicator with no pauses to speed the runs up and set up a series of IF_THEN_STOP statements if any of the conditions were met. Sure enough 2997,2998 and 2999ms were within the program range and stopped the program.Code:main: Random X Y = X * 1000 Z = DIV32 21845 SEROUT2 PORTC.3, 16780, [DEC Z, 13, 10] IF Z = 2997 THEN STOP IF Z = 2998 THEN STOP IF Z = 2999 THEN STOP IF Z = 3000 THEN STOP IF Z = 3001 THEN STOP GOTO main
Then for the big one 3000ms, that was also there and stopped the program!
What about 3001.....Nope, the program runs from 1 to 3000ms absolutely stop on.
Henrik, mackrackit, thank you both and good night.
Dave
Last edited by LEDave; - 10th July 2010 at 00:29.
Dave
Always wear safety glasses while programming.
Hi Dave,
It can't ever be more than 3000ms because the highest value possibly returned by Random is 65535, anything larger won't fit in the WORD variable. We multiply that by 1000 and divide it by 21845 resulting in 3000. So, with these numbers it's simply impossible to get anything "larger" than 3000.
/Henrik.
Me and Rube have a lot in common, he draws them and I make themGoldberg is best known for a series of popular cartoons he created depicting complex devices that perform simple tasks in indirect, convoluted ways.
Hi Henrik, I can appreciate that, I thought it was just cool to be able to see the numbers via the Serial Communicator.It can't ever be more than 3000ms because the highest value possibly returned by Random is 65535, anything larger won't fit in the WORD variable. We multiply that by 1000 and divide it by 21845 resulting in 3000. So, with these numbers it's simply impossible to get anything "larger" than 3000.
What did you think of the way in which I made the program run using VARS: X,Y and Z?
Dave
Hi Dave,
Nothing wrong at all with the way you did it. However, it seems to me you are "wasting" four bytes of RAM with the use of Y and Z. If you don't need to massage the intermediate results it's perfectly OK to simply use a single WORD variable, like/Henrik.Code:X VAR WORD RANDOM X X = X * 1000 X = DIV32 21845 SEROUT2 PORTC.3, 16780, [DEC X, 13, 10]
Hi Henrik,
Here's a strange thing (and I'll re-check this later). I originally ran the code as yours above and the output was something like: 2411-341-11-0-0-0-0-0. After only a few cycles it started outputting zero's.
I may well have made a 'typo' myself here so I'll re-check and re-run later today.
Dave
Last edited by LEDave; - 10th July 2010 at 10:41.
Hi Dave,
Actually, it looks like you got me on this one... I'll HAVE to start verifying what I write before trying to look like I know what I'm talking about ;-) Don't know what's going on here, I'll have to try a few things out.
/Henrik.
EDIT: OK, I'm not sure exactly what's going on but this does seem to work:Thanks Dave for catching that and letting me know!Code:RANDOM X Y = X * 1000 Y = DIV32 21845
Last edited by HenrikOlsson; - 10th July 2010 at 11:31.
Henrik,
I think our student has been reading the manual and caught the "dummy" var in the examples given.
I think our student has also increased in rank!
Maybe now he is
NEWBIE.2
Dave
Always wear safety glasses while programming.
mackrackit.
It was reading the DIV32 example that made me use the X,Y,Z VARS. Although I must fess_up and say that I wasn't 100% sure I'd spotted the 'right' typo in Henriks post.I think our student has been reading the manual and caught the "dummy" var in the examples given.
Lol, I'm getting better but maybe NEWBIE1.5.......I think our student has also increased in rank! Maybe now he is NEWBIE.2
Dave
Following on from and using the theory we've already covered. I thought it might be a good idea to try and make the RANDOM time pause generated from the previous program slightly more RANDOM.
I noticed with the last program that RANDOM always 'seeded' with the same start value at power up a (2522_Mili_secs) pause and then followed the same number sequence on the display. So if you powered up and powered down the program in fairly quick succession you'd soon notice the start sequence wasn't that RANDOM at all, it was exactly the same!
So I got to thinking what if, when the program 'powered down' I saved the last RANDOM value in EEPROM memory and then re-loaded that value as the start 'seed' on 'power up' that would then continue the 'RANDOM' sequence (ok, RANDOM from 1-65535) so pretty RANDOM unless you're a memory man.
Here's the code I came up with (I changed from the Serial Communicator to LCD (why not, all good practice)). It seems to work too.
The program continually WRITES to EEPROM whilst the program runs but only READS from EEPROM on power_up. What do you think?
CODE:
DaveCode:X VAR WORD Y VAR WORD Z VAR WORD 'STORED IN EEPROM LOCATIONS 0 AND 1 Start: goto Power_up: 'Load STORED last RAND_VAL Power_up: 'Power_up subroutine Read 0, Z.HIGHBYTE 'Read VAL_Z_high byte Read 1, Z.LOWBYTE 'Read VAL_Z_low byte LET X = z 'SEED X with the VAL Z GOSUB RAN: RAN: Random X 'RANDOM program cycle continues Y = X * 1000 Z = DIV32 21845 LCDOUT $FE,2,"MSECS=",DEC4 Z 'LCD displays RAND_VAL PAUSE Z 'Program PAUSES for 'Z_Mili_secs' HIGH PORTA.2 'LED PORTA.2 lights up PAUSE 500 low PORTA.2 'LED off WRITE 0, Z.HIGHBYTE WRITE 1, Z.LOWBYTE GOTO RAN
Last edited by LEDave; - 12th July 2010 at 15:45.
Hi Dave,
A couple of small things noticed:
1) You can read the value direct into X instead of first reading it to Z and then copying it to X. Nothing wrong with what you're doing it'll just save some program space and time.
2) The line GOSUB RAN: looks strange. First, there shouldn't be any colon after the label in the jump statement, only where you declare the actual label. Second, you don't want to GOSUB a routine from which you don't RETURN. In this case it may work but it's generally a bad idea.
3) Speaking of GOSUB and GOTO, you are making a couple of unneccessary jumps. At the beginning you say GOTO Power_Up even though the next line in the program is the beginning of the Power_Up routine. Same thing when Power_Up is done, then you jump to RAN which already is the next line so it will get there without needing to jump to it.
Now, if you have some other code "in between" then it makes sense, and as you've found it, it works the way you have it but it's not needed.
4) The EEPROM has a limited number of write-cycles. We're talking tens or even hundreds of thousands of cycles but if you write to it on average ever 1500ms, 100.000 writes are less than 42 hours.
There are ways to get around that but it requires a little hardware and the use of interrupts. Basically you have a capacitor that allows the PIC to stay powered long enough to make the EEPROM writes. The capacitor is charged from your powersupply thru a diode. Then you have a "direct" wire going to an input on the PIC which fires an interrupt when the powersupply goes down (the cap is keeping the PIC alive).
Again, just a couple of small things to consider. Good job!
/Henrik.
Thanks for the pointers Henrik. Some lax programming there to say the least, I do agree. I'll have to sharpen things up. I did have a push button loop in there at one stage IF - THEN - LABEL but took it out and in my rush / excitement to get the program to work made things look untidy.
I remember mackrackit commenting on the write cycles of an EEPROM, I was mindful of that, again my rush to get it to work overroad it and I looked the other for now.4) The EEPROM has a limited number of write-cycles. We're talking tens or even hundreds of thousands of cycles but if you write to it on average ever 1500ms, 100.000 writes are less than 42 hours.
To be honest I was pleased that the write to EEPROM idea worked (or seemed too).
Thanks again.
Dave
Use the EEPROM idea but write to the EEPROM once during run time.
But before you write Z, maybe add 37 or something to it.
Dave
Always wear safety glasses while programming.
Now why couldn't I have thought of that.....Use the EEPROM idea but write to the EEPROM once during run time.
But before you write Z, maybe add 37 or something to it.
I went to use the rfpic transmitter the other day and the battery was flat, would the module continually be draining power with the battery in place or was it just that the battery was unused but old do you think?
Dave
The EEPROM thing was your idea...
Sounds like a weak battery or the transmitter was stuck on transmit.
Can you check the amps when "not in use" ?
Dave
Always wear safety glasses while programming.
Bookmarks