PDA

View Full Version : how to generate two signals from two ports at the same time by using p16f84



bikxsici
- 28th July 2011, 09:23
hi

for my homework i am supposed to build a circuit by using pic16f84 generating two squarewave signals having different selectable precision frequencies such that 2,2 khz or 2,4 khz etc. throughout different ports at the same time.

i have used tmr0 and other some methods to build it too much but i could not generate that precision frequencies. it seems so diffucult!!!

thanks for all helps

mackrackit
- 28th July 2011, 09:58
Have you read this thread?
http://www.picbasic.co.uk/forum/showthread.php?t=14652&page=1

bikxsici
- 28th July 2011, 10:31
let me look at

bikxsici
- 28th July 2011, 10:49
i guess if pic16f84 have had 2 timers , it would be easy but it has not and how do we generate two different signals by using one timer at the same time?

so diffucult

cncmachineguy
- 28th July 2011, 12:13
the program i posted in that thread uses 1 timer. That timer is used to generate a time base to drive 4 software counters. these counters become my timers.

bikxsici
- 28th July 2011, 12:35
hi cncmachineguy

yes i recognized it but pic16f84 drived by max 10 mhz and we need so precision time period , max +-2 micro second precision, when we use instructions like if ,else we have problem.

when we are asked to generate two signals 630 micro seconds and 453 micro second by porta.0 and porta.1, for example, 633 micro seconds is not acceptable.

cncmachineguy
- 28th July 2011, 13:08
well how about you post what you have so far, and maybe we can help you to get it done. Did you teacher have any suggestions how he thinks you will do it? I am sure there are several ways to get it done, but you must understand how and why it works. We will help you, but we won't do it for you (not saying you asked us to). So show us what you have and we can go from there.

bikxsici
- 28th July 2011, 13:45
yes i have an advisor teacher but he does not say anything about how i can do it. i guess he just wonder how i find a solution for this project.

i have started usual basic loop without using tmr0, and for a signal it works well but generating second one with different frequencies causes timing problem. i also tried to implement assembler codes in order to have more time space however it did not help me.

at least i want to find a method so as to generate these signals having pulse witdh x8 ( 8,16,..320 mic. sec ). in this program i am trying to use basic timing by using tmr0 and interrupt. i guess i need a 8 micro seconds time period which constant?

thanks a lot


define OSC 10
timer0 var word
timer1 var word

A0 VAR PORTA.0
A1 VAR PORTA.1


on interrupt goto int_timer

OPTION_REG=%00000000
TMR0=255
INTCON=%10100000

TRISA=0
LOW PORTA

timer1=0
timer0=0


enable
main:

goto main

disable
int_timer:

timer0=timer0+1
if timer0=>3 then ' 3 is a random number
timer0=0
toggle a0
else
endif

timer1=timer1+1
if timer1=>10 then ' 10 is a random number
timer1=0
toggle a1
else
endif


INTCON.2=0
TMR0 = 255
resume

end

bikxsici
- 28th July 2011, 13:48
i have tried to obtain accurate time by changing tmr0 and prescaler, but still no answer :(

mackrackit
- 28th July 2011, 14:03
You have a lot of stuff in the ISR. Take the IF_THEN_ELSE out of the ISR.

bikxsici
- 28th July 2011, 14:11
yes, i have tried it also, i put them in main loop but i could not obtain time accuracy.

bikxsici
- 28th July 2011, 14:26
i need a loop with constant 8 mic. sec. time period and multiplying it with two different variables to obtain to different signal. but how?

mackrackit
- 28th July 2011, 14:35
How fast are you allowed to run the MCU?

mackrackit
- 28th July 2011, 14:39
http://www.picbasic.co.uk/forum/content.php?r=159-New-PIC-Utility.-PICMultiCalc

bikxsici
- 28th July 2011, 14:44
i am allowed to use pic16f84 and 10 mhz crystal. i think this project is impossible, since i have struggled so much, but unfortunately he has a circuit doing that with pic16f84 :0

bikxsici
- 28th July 2011, 15:25
thanks a lot mackrackit

that utility makes me more careful about timer. now let me review my program again

cncmachineguy
- 28th July 2011, 19:04
Your first post said you needed to be able to select 2 frequencies. How are they selected? If they are just hardcoded in and there is nothing in the "main", there is no need for an interrupt. You can do it all from the main routine. This will save all the time required to process the interrupt.your code would have 1 line looking for the timer overflow such as :

while !tmr0 overflow
wend

then load 2 counters, 1 for each output


freq1 = period / timer0
freq2 = period2 / timer0

then on each overflow, decrement the freq's. when 1 reaches zero


if !freq then
toggle output bit
reload freq
endif

now don't forget to reload the timer unless you can set it up to just free run. You will need to play with the freq's counter numbers to "tune" the output, but I suspect you can get it right on the money.

bikxsici
- 29th July 2011, 13:06
hi cncmachineguy

dividing two variables by tmr0 and obtaining two periods from tmr0, it seems to work, but i think there can be some problems. for example, should we reload tmr0 with respect to which signal? for the first pulses ok but then when next period start?

program below is what you said, isn't it? thank you for advices




OPTION_REG=%00000000
TMR0=0
INTCON=%10100000
main:
while tmr0>=250
tmr0= 0
wend

freq1= per1 / timer0
freq2= per2 / timer0

if freq1<1 then
toggle a0
per1=100
else
endif

if freq2<1 then
toggle a0
per2=200
else
endif
goto main

bikxsici
- 29th July 2011, 13:17
second one should a1 :( sory

cncmachineguy
- 29th July 2011, 13:51
You are close to what I mean. TMR0 Should be setup as a time base, you had mentioned 8uSec in another post. So compute the reload value for TMR0 such that you get an interrupt flag at 8uSec. (hint: use PicMultiCalc to help get the values)

Next the freq values are computed by YOU and hardcoded. so if TMR0 is 8uSec, and you need a period of 800 uSec, freq will be 800/8 or freq = 100.

Your while loop just needs to check for TMR0 interrupt flag bit. You do not want to enable interrupts, but the flag will be set anyway. So as soon as the flag is set you need to do this:


reload the TMR
clear the flag
decrement freq1 &freq2
check each for zero (IF !freq1 then) this will check if freq1 = 0

I will let you work on how to actually code the above. You almost have the Freq checks correct. Put comments in your code. This will do 2 things:
1 tells others and yourself what things are doing. If you code more beyond this class, you will be VERY happy you started doing this.
2 When you comment what you think things are doing, It will make it easier to see what is wrong. Here is a for instance:


while tmr0>=250 ' this line checks if TMR0 is greater then 250
tmr0= 0 'this line sets TMR0 to equal 0 if it is greater then 250
wend ' this is where the program jumps to when TMR0 is less then 250


This will not work ok, the ugly is all your program will run while waiting for the timer to reach 250. Then when tmr does reach 250, you just set it back to zero. Effectively tmr0 is doing nothing for you here. I will leave it to you to try to figure out why.

BTW, I am in no way a very good teacher, so please bear with me. My goal is to give you clues and help you to understand what is going on as opposed to telling you how to do each step. Is there a deadline when you must be done?

bikxsici
- 29th July 2011, 15:44
sory i am writing fast and i forget something. there is no deadline but i must submit as soon as possible.

i am going to review the program, and i will send the results , i must be careful. thanks a lot for your advices

best regards

bikxsici
- 31st July 2011, 12:15
hi cncmachineguy

i think there are two choices which depend on whether the codes ( decrement freq1 &freq2, IF !freq1&&freq2 then) are in interrupt loop or main loop.

for the first one, they are in the interrupt loop, these codes takes min 10 mic. sec. ( with adjusting option_reg, and loading tmr0 for min. time ) , therefore i can not obtain a period increment below 10 mic. seconds.

for the second one, i have tried to put those codes into main loop, but then i have problem to control tmr0 to obtain exact values.

after so much efforts i have decided to build this system is impossible by using pic16f84 with 10 mhz and i think we need at least two timer interrupts to obtain two different precise frequencies.

thank you a lots for advices.

cncmachineguy
- 31st July 2011, 15:28
I understand your frustration, but don't give up yet. Your teacher has it working so it is not impossible.

New question, you say you need 2uSec percision, but then you talk about using an 8uSec time base. this will not be able to provide 2uSec percision. So is the 8uSec ok?

lets look at some math for a minute. you have a 10Mhz clock, so thats 2.5MIPS. each instruction will take .4uSec, so for 8uSec time base, you have 20 inscrutions worth of time to decide what to do.

If you don't want to give up, lets keep working on this.

bikxsici
- 1st August 2011, 09:47
yes 8u sec. is also ok. let's look at it closely again ( by the way i hope i am a good student ) maybe this time we can do it. i think there is no problem about timing by using tmr0 and prescaler, it works well. the main problem is that we need a loop including two variables depending on tmr0 and to determine intended two periods time.
i think putting this loop into interrupt is better since if we have had to use a keyboard to select frequencies, we would use it in the main loop, so no waste time for our periods.
but on the other hand when we use below codes in the interrupt loop, it needs 22-25usec.. i am writing codes below how i calculate these times. i get 22-25 usec. by measuring pulse width of porta.1 via oscilloscope.

int_loop:
high porta.1 ; start of the pulse i measure

fre1=fre1+1 ; increment for period 1 depending on tmr0 interrupt time
fre2=fre2+1 ; increment for period 2 depending on tmr0 interrupt time

if fre1>=5 then ; 5 random number if i suceed it will be fraction of x8
toggle porta.0
fre1=0
else
endif

if fre2>=3 then ;3 random number if i suceed it will be fraction of x8
toggle porta.0 ; this must be porta.1 but now not important
fre2=0
else
endif
INTCON.2=0 ; setting up timer
TMR0 =254 ; reload tmr0

low porta.1 ; end of pulse

pauseus 100
goto int_loop


and this is the shotest loop i know for our aim, and it requires at least 20usec bigger than 8usec. :((

thanks a lot

cncmachineguy
- 1st August 2011, 12:08
OK, Good start. First I think this will have to be your main and grabbing input will have to be your interrupt. I say this because even if you used pure ASM to get in the ISR, it will take at least 8 ASM instructions for the context save and restore. This leaves you almost no room to do anything. On the other hand, if the signalk generation is the main, with an interrupt call for the keypress, maybe it will be ok. you will get a glitch or 2, but only when you change freq.

No, lets see how to speed this up a bit.
First remove the else statements. you are not using them so you can get rid of them. I don't think this will speed it up, but lets see.

After you try that, change the counters to count down instead of up. Checking if freq = 0 should be much faster then if freq >= something. The reason for this is in the compiled code, it should compile to be something like this:


DECF freq 'decrenment freq
BTFSS freq 'test if freq is zero, if not skip the next step
JMP notzero
MOVLW 5
MOVF freq
notzero:
reutrn

In order to test for equal or greater then any number other then zero, first the number must be subtracted from the counter, then status.zero must be tested. If not zero, then borrow or carry must be tested and the program will branch accordingly. Does this make sense?

After you try these 2 things, report back with the results. There is at least 1 more thing we can do, but I want you to try each thing 1 at a time and understand why it worked or didn't work.

cncmachineguy
- 1st August 2011, 12:17
Forgot to mention, No need for a prescaler, 8uSec is WAY shorter then TMR0 just running. In fact, we may find the loop can be tuned to take EXACTLY 8uSec, so no need for the TMR at all! :)

But first we must get through timing tests as you are doing now.

Yes, you are a fine student, just don't give up.

1 more thing, does the language used matter? As a last resort we will try this with ASM. What type of class is this for?

bikxsici
- 1st August 2011, 13:23
yes you are right maybe we can do it without using TMR. for a language, normally we must use ASM but also can use PBP or C, but i prefer PBP since i have learned it before. it is a summer course, introduction to microprecessor, in my university and homework will not collected but i want to do it since firstly it seemed very easy but after struggling i think infact it is not easy and makes us more careful about timing.

now, i want to use PBP and we can put ASM codes and by using PEEK nad POKE we can change and get ASM variables in PBP, i hope there will not be a problem.

but before i want to write it via MPLAB to see exact timing and then put it in PBP. By the way the issue about if=0, you are right, i did not recognize it. i am going to try some codes and share results here.

best regards