PDA

View Full Version : Triggering 5 TTL clocks simultaneously



TurboLS
- 19th February 2005, 04:44
OK, this code is written to wait for an interrupt, then clock out 784x512 bytes of data. The only chunk of the code shown is that which controls the clocking scheme. My question is if there is any way to execute time sensitive commands faster than the 1 usec instruction time. Thanks for all the help.

horizpulse var byte
vertpulse var byte

horizpulse = 1
vertpulse = 1
PORTB.0 = 0 ‘portb.0 is the Vphase1 clock
PORTB.1 = 0 ‘portb.1 is the Vphase2 clock
PORTB.2 = 1 ‘portb.2 is the Hphase1 clock
PORTB.3 = 0 ‘portb.3 is the Hphase2 clock
PORTB.4 = ‘portb.4 is the reset clock

buttonloop:
IF PushButtonOnPORTABIT2 = 1
THEN GOTO vertloop ‘waits for 5V that signals shutter is closed
ELSE GOTO buttonloop
vertloop:
horizpulse = 1
PORTB.0 = 1
PAUSEUS 139
PORTB.0 = 0
PORTB.1 = 1
PAUSEUS 139
PORTB.0 = 1
PORTB.1 = 0
PAUSEUS 139
PORTB.0 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512
THEN GOTO horizloop
ELSE GOTO buttonloop
horizloop:
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
PORTB.3 = 0
PORTB.2 = 1
PAUSEUS 139
horizpulse = horizpulse + 1
IF horizpulse < 784
THEN GOTO horizloop
ELSE GOTO vertloop
END

mister_e
- 19th February 2005, 10:16
My question is if there is any way to execute time sensitive commands faster than the 1 usec instruction time


use a faster crystal.. depending of your PIC... some can run up to 40MHZ.

so in this case... 0.1 usec by SOME ASSEMBLER instruction

TurboLS
- 19th February 2005, 15:55
I was also toying with the idea of just setting the registers in one line, like

PORTA = %11001010

or something to that effect, but I have no idea how I would loop that.

mister_e
- 19th February 2005, 17:03
if you want to send 8 bits of data to PORTA in one shot... yes PORTA=MydataToSend will be what you need. Be sure that you have set the TRISA register before that
TRISA=255

TurboLS
- 21st February 2005, 21:27
Ok, here is my updated code, now I just have a few questions:

1.) Is there a way to split PORTA into analog and digital inputs?
2.) PORTB.4 is the reset clock and basically it has to be pulsing as soon as the microcontroller powers up. The problem is that once i start the other clocks, the time at which the reset goes high has to be in synch with H1 going low and H2 going high. In addition, it's high duration is 1/4 of the high time of the horizontal clocks. I will post up a timing diagram to explain what i mean later today. So basically I can't just put it in one of my loops, I have to start it pulsing at like a 25% duty cycle and when the other clocks are going, it has to be in synch with the horiztonals like i said earlier.

any help is appreciated.

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Vphase1 clock
' PORTB.1 is the Vphase2 clock
' PORTB.2 is the Hphase1 clock
' PORTB.3 is the Hphase2 clock
' PORTB.4 is the reset clock
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz
Define ADC_CLOCK 4 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00000010 ' Set PORTA analog
TRISB = %00000000 ' Set PORTB to all output
Pause 500 ' Wait .5 second

Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.0 = 0
PORTB.1 = 0
PORTB.2 = 1
PORTB.3 = 0
PORTB.4 = 0

buttonloop:
IF PushButtonOnPORTABIT2 = 1
THEN GOTO vertloop ' Waits for 5V that signals shutter is closed
ELSE GOTO buttonloop
vertloop:
horizpulse = 1
PORTB.0 = 1
PAUSEUS 139
PORTB.0 = 0
PORTB.1 = 1
PAUSEUS 139
PORTB.0 = 1
PORTB.1 = 0
PAUSEUS 139
PORTB.0 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512
THEN GOTO horizloop
ELSE GOTO buttonloop
horizloop:
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
PORTB.3 = 0
PORTB.2 = 1
PAUSEUS 50
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSE 87
horizpulse = horizpulse + 1
IF horizpulse < 784
THEN GOTO horizloop
ELSE GOTO vertloop
END

mister_e
- 21st February 2005, 21:39
1.) Is there a way to split PORTA into analog and digital inputs?

for sure... see datasheet in the A/D section.. ADCON1 TABLE 19-2

will be interesting to have kind of flowchart and schematic for the other problems you have.

Darrel Taylor
- 21st February 2005, 22:07
TurboLS,

What version of PBP are you using? I've never seen this work in any versions I've had.

IF vertpulse < 512
THEN GOTO horizloop
ELSE GOTO buttonloop

I've wanted to use that type of syntax before, but I get nothing but errors. Did I miss an update or something. I have 2.45

Darrel

TurboLS
- 21st February 2005, 22:22
I am using 2.46 and I will have a pic up soon that has the timing scheme. thanks for the replies.

TurboLS
- 21st February 2005, 22:52
here is the timing diagram. notice how the reset, H1, and H2 are in synch at the lower right. Also notice that the reset is going all the time, even when the other 4 clocks are not.

please click the link and scroll to page 13

http://www.kodak.com/global/plugins/acrobat/en/digital/ccd/products/fullframe/KAF-0402ELongSpec.pdf

thanks.

TurboLS
- 21st February 2005, 23:05
Oh yeah, i am gettin some errors from that if else stuff too.... gonna have to find a way around that arghhhh!

scratch that, you just have to put all the commands on the same line, like so:

IF vertpulse < 512 THEN GOTO horizloop ELSE GOTO buttonloop

however, i still have 9 errors to fix before mine compiles properly.

TurboLS
- 21st February 2005, 23:37
Also, I tried looking at the ADCON1 register, and i guess if I am reading from the table properly... to set PORTA.2 to digital in, I should say ADCON1 = %00001101 cuz that's where the D and the AN2 meet.

I am still having a problem with the OnPushButton command and apparently I have to use END IF commands, which I am not sure how I will implement just yet.

TurboLS
- 21st February 2005, 23:48
I got it down to 6 errors, all with my IF statements. Here is what I have for a generic IF line:

IF PushButtonOnPORTABIT2 = 1 THEN GOTO vertloop ELSE GOTO buttonloop

on the following line i have

ENDIF

and doing that got rid of 3 of the errors, but now I need to figure out why it doesn't like my then goto / else goto commands.

For each of my 3 if statements, I get

bad expression
bad expression or missing then

TurboLS
- 22nd February 2005, 00:19
OK, i know i have been posting a lot lately, but now i am down to 2 errors, both associated with

IF PushButtonOnPORTABIT2 = 1 then

I think it has something to do with me setting the ADCON1 register incorrectly.

TurboLS
- 22nd February 2005, 00:26
OK, I fixed it (I think) to where I have no compiler errors.

basically I had to change the above line to

IF PORTA.2 = 1 then

mister_e
- 22nd February 2005, 00:33
IF vertpulse < 512 THEN GOTO horizloop ELSE GOTO buttonloop


I prefer like this



IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF


Using Alias to i/o


TRISA = 255 ' Set PORTA as input

PushButton1 var PORTA.0
PushButton2 var PORTA.1
PushButton3 var PORTA.2

IF PushButton1 then ' Same as PushButton=1
' do your stuff here
ENDIF

TurboLS
- 22nd February 2005, 03:31
So yeah I am still stuck with the whole reset clock thing. Is there a way I can generate a clock in hardware that is not a 50% duty cycle? By using one of the timer functions perhaps?

I was also wondering approximately how fast each of the commands in my program would take to process. Knowing that, I would be able to generate the reset clock by estimating the time in usecs.

thanks again for all the input.

mister_e
- 22nd February 2005, 03:43
One thing i figure is to use the OSCLKO pin and connect to RB0 or else interrupt source. Once you'll be the in the interrupt routine, you'll be able to do everything. Generate all your delay and pin level. Will be a bit tricky to get the perfect timing but not impossible.

If you want to generate a 4MHZ clock, you'll need a 8MHZ crystal. Interrupt on rising or falling edge. Interrupt routine will generate your R, H1 and H2 frequency in one shot.

Depending your crystal speed, your instruction will be executed in few msec or less.

BUT for that kind of stuff where accuracy and precision is important, you'll probably need to do your delay and some test in assembler. Assembler instruction can be executed in 1 or 2 frequency cyle. Let's say at 8MHZ, 1 intruction every (1/(8Mhz/4)) = 0.5 uSec. Can be usefull to have a PIC who have an internal PLL to multiply your cystal speed.

If you have a 8MHZ crystal, execution time will be 4 times faster so from 0.5uSec to 0.125 uSec.

TurboLS
- 22nd February 2005, 04:05
The reset, H2, and H1 will be about 3.6kHz. I don't know if there is a way I can get that with the multipliers.

Is there like a table where I can calculate the execution times? I know that "time-sensitive" commands take 1 usec with a 20Mhz clock (which is what I am using).

How long do if statements and such take, jumps to different parts of the program (like when I use the GOTO commands)?

mister_e
- 22nd February 2005, 06:14
if they are constant... you can use HPWM on 2 channel... 2 different duty but the same frequency. They will run in background and they will not be interfered by anything else.

OR you can use the internal TIMER1 16bit and do you delay stuff when you get TIMER1 overflow interrupt.

at 3.6 KHZ period = 277.777 uSec

let's say you'll use a 20Mhz crystal... internal frequency 5MHZ period = 0.2 uSec = 1388.888 internal clock count. We want to change state every 1/2 period. 1388.888 uSec / 2 = 694.4444 uSec. So you'll have to preload Timer1 to 65535-694 = 64841 or $FD49.

here's a snippet to produce 3 different duty cycle with TIMER1


' program to generate Multiple duty cycle @ 5 mhz on PORTC
' Use of PIC18F2220
'
@ __CONFIG _CONFIG1H, _HS_OSC_1H
' HS

@ __CONFIG _CONFIG2L, _BORV_20_2L & _BOR_ON_2L & _PWRT_ON_2L
' BOR Voltage - 2.0v
' Brown-Out Reset enabled
' Power-Up Timer enabled

@ __CONFIG _CONFIG2H, _WDT_ON_2H
' Watch Dog Timer enabled

@ __CONFIG _CONFIG3H, _MCLRE_ON_3H & _PBAD_DIG_3H & _CCP2MX_ON_3H & _CCP2MX_B3_3H
' MCLR enabled
' PORTB<4:0> pins reset as digital pins
' CCP2 pin function on RC1
' CCP2 pin function on RB3 (alt defn)

@ __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_ON_4L
' DEBUGger disabled
' Low Voltage Prgramming disabled
' Stack over/underflow Reset enabled

@ __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
' Block 0 readable/ may be writable
' Block 1 readable/ may be writable

@ __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
' Boot Block readable / may be writable
' Data EE memory readable / may be writable

@ __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
' Block 0 writable
' Block 1 writable

@ __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
' Config registers writable
' Boot block writable
' Data EE writable

@ __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
' Block 0 readable
' Block 1 readable

@ __CONFIG _CONFIG7H, _EBTRB_OFF_7H
' Boot block readable

DEFINE OSC 20
TRISC=0
INTCON = %01000000 ' enable peripheral interrupt
PIE1 = %00000001 ' enable TIMER1 overflow interrupt
TMR1L=$49
TMR1H=$FD
T1CON = %00000101 ' prescaler 1:1
' Clock source = Fosc/4
' start the timer1
on interrupt goto TMR1_Overflow
Passes var bit
clear
START:
goto start

disable
TMR1_Overflow:
T1CON.0=0 'stop timer
PIR1.0=0 ' reset interrupt flag
TMR1l=$49
TMR1H=$FD
T1CON.0=1 'start timer
if Passes then
PORTC = 6
pauseus 69
PORTC = 4
passes= 0
else
PORTC = 1
passes= 1
endif
resume
enable


you may need to adjust the value of the TIMR1L to fine tune your frequency.

To calculate or to know the time an instruction take, you can use MPLAB's stopwatch... give a great aprox of the time.

TurboLS
- 22nd February 2005, 16:19
I was thinking of doing the reset on one of those HWPM things because the reset is the only constant clock. Then I could just do a conditional statement to make sure that the reset and the horizontal clocks are in synch. The good thing about that, like you said, it would run in the background and so I could run all the other clocks just as I had them. What do you think??

mister_e
- 22nd February 2005, 18:07
Then I could just do a conditional statement to make sure that the reset and the horizontal clocks are in synch

mmm, IMO you can't check with internal to synchronize them. I figure you'll have to use an extra i/o to read from the PWM output. Once you get the highlevel or interrupt, you do your Horizontal stuff. A microsecond or less of
delay between to rising edge of Reset and your Horizontal... but at 3.6KHZ i can't figure it will be a big problem.

TurboLS
- 22nd February 2005, 19:21
So you're saying something like:

IF PWM output is high, start the horizontal clocks

Yeah, using another I/O pin is not a problem, cuz at this point i think i am using 2 pins of portA

How would I go about getting the HPWM to oscillate at 3.6kHz with a 25% duty cycle? I will look at the manual again later today or tomorrow probably and see if i can figure it out.

thanks again, you are a huge help.

mister_e
- 22nd February 2005, 19:25
it's a bit more than if pin is high... IF the according pin is at the rising edge of the signal... this ensure the right timing. Use interrupt source INT0, INT1 or else you can have on the rising edge... will be really easy now. The only thing you have to care about is the timing and latency in the other routines to get interrupt as quick as possible.

For the HPWM frequency and duty cycle, try

HPWM 1,64,3600 ' supposed to send HPWM 3.6KHZ at 25% duty

i don't know how accurate it will be. In my purpose i always set all the register myself. In your datasheet they tell you how to calculate everything.

TurboLS
- 22nd February 2005, 19:50
What pin would that HPWM be coming off of??

mister_e
- 23rd February 2005, 01:44
HPWM channel = CCP1 of your 18F4520 = PIN RC2 PIN 17

TurboLS
- 23rd February 2005, 18:01
So I guess I could have it running in the background, then when I want to start the horizontal clocks, I could do an ON INTERRUPT command to make sure it is on the rising edge of the Reset HWPM clock.

mister_e
- 23rd February 2005, 20:49
you don't have to make sure it's on the rising edge. Interrupt will do it for you. When you set your interrupt you can select rising or falling edge.

TurboLS
- 23rd February 2005, 22:37
And I set that in the registers, right? And then I can run a wire from PIN 17 to an interrupt pin and do an ON INTERRUPT command? Would it look something like this or totally different? I am going to try and find some examples.

horizloop:
ON INTERRUPT
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
PORTB.3 = 0
PORTB.2 = 1
PAUSEUS 50
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSE 87
horizpulse = horizpulse + 1
IF horizpulse < 784

mister_e
- 23rd February 2005, 22:54
NOP...

i'll have more spare time tomorrow for that... BUT have a look on this thread (http://www.picbasic.co.uk/forum/showthread.php?t=1026) download the code i did. It use the interrupt on an pin to do specific task. Can be handy to start. Code is well documented.

ON INTERRUPT GOTO define the place to go when an intterupt happen. See PBP manual on that statement. care will have to be made in the interrupt routine too. sould not be too loang... at minimum less than the time between each interrupts.

TurboLS
- 24th February 2005, 19:58
Well I would think I would only need one in the loop, just to make sure the Reset(HWPM) and Horizontal 2 are on their rising edge as in synch as possible.

TurboLS
- 24th February 2005, 20:11
What if I did something like this??

horizloop:
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
ENABLE
ON INTERRUPT GOTO H2lock
DISABLE
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF

H2lock:
PORTB.3 = 0
PORTB.2 = 1
RESUME

mister_e
- 24th February 2005, 20:25
NOP, On Interruot goto is placed at the header of your code before your main loop. Since it's working in background, it will jump by himself to the interrupt routine. did you look at my previous link?

INTCON and probably others have to be set for interrupt type/source.

i'll make something like this later today.

TurboLS
- 25th February 2005, 01:08
What do you think of something like this>?

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Vphase1 clock
' PORTB.1 is the Vphase2 clock
' PORTB.2 is the Hphase1 clock
' PORTB.3 is the Hphase2 clock
' PORTB.4 is the reset clock
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz
Define ADC_CLOCK 4 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

ON INTERRUPT GOTO H2lock ' When Reset clock is high
INTCON1 = %1001000 ' Enable RB0 Interrupt
INTCON = $80 ' Disables Interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001101 ' Set PORTA analog, except for pin 2
TRISB = %00000000 ' Set PORTB to all output
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.0 = 0
PORTB.1 = 0
PORTB.2 = 1
PORTB.3 = 0
PORTB.4 = 0

buttonloop:
IF PORTA.2 = 1 then
GOTO vertloop
else
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.0 = 1
PAUSEUS 139
PORTB.0 = 0
PORTB.1 = 1
PAUSEUS 139
PORTB.0 = 1
PORTB.1 = 0
PAUSEUS 139
PORTB.0 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF
horizloop:
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
INTCON = $80 ' Re-enables interrupts
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF

DISABLE
H2lock:
PORTB.3 = 0
PORTB.2 = 1
RESUME
ENABLE
END

TurboLS
- 25th February 2005, 01:55
Also, I saw a blurb in the PBP manual about the fact that I can check the interrupt flag without actually enabling interrupts. If I did it that way, then I could merely do a check condition statement, similar to this, right?:

IF PORTB.2 = 1 AND INTERRUPTFLAG = 1 ' When horizontal 1 is high and reset is high

' Do the H1 > low, H2 > high, ADC conversion and the SEROUT2

TurboLS
- 26th February 2005, 03:54
OK, I checked the datasheet and the interrupt flag bit is bit 1 of the INTCON register. It also says that I have to reset it in software once an interrupt has occurred. So I was thinking if I just set the INTCON.1 = 0 right before the condition statement, then I could just wait until the INTCON.1 = 1 before clocking the horizontals. What do you think?

Bruce
- 26th February 2005, 04:26
Yep. I do this all the time.

Disable global interrupts (INTCON.7 = 0), and just monitor & reset interrupt flags as needed. Very handy.

TurboLS
- 26th February 2005, 05:21
Should I still enable the INTCON1 register? I have it set to %1001000 to use the RB0 interrupt. I have the HWPM (which is to be the interrupt source) set as follows:

HPWM 1,64,3600 ' Supposed to send HPWM 3.6KHZ at 25% duty

TurboLS
- 26th February 2005, 05:24
I tried compiling that and I get

Symbol not previously defined (INTCON1)

The updated code is as follows:

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Vphase1 clock
' PORTB.1 is the Vphase2 clock
' PORTB.2 is the Hphase1 clock
' PORTB.3 is the Hphase2 clock
' The reset will be connected to a HWPM clock pin #17
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz
Define ADC_CLOCK 4 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

HPWM 1,64,3600 ' Supposed to send HPWM 3.6KHZ at 25% duty

INTCON1 = %1001000 ' Enable RB0 Interrupt
INTCON.7 = 0 ' Disables global interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001101 ' Set PORTA analog, except for pin 2
TRISB = %00000000 ' Set PORTB to all output
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.0 = 0
PORTB.1 = 0
PORTB.2 = 1
PORTB.3 = 0

buttonloop:
IF PORTA.2 = 1 then
GOTO vertloop
else
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.0 = 1
PAUSEUS 139
PORTB.0 = 0
PORTB.1 = 1
PAUSEUS 139
PORTB.0 = 1
PORTB.1 = 0
PAUSEUS 139
PORTB.0 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF
horizloop:
INTCON.1 = 0 ' Resets interrupt flag to 0
Resetcheck: ' Loops back to make sure
PAUSEUS 2 ' the PORTB.2 goes low and
IF INTCON.1 = 0 THEN ' PORTB.3 goes high as close
GOTO Resetcheck ' to the external trigger's
ELSE ' rising edge as possible
ENDIF
PORTB.2 = 0
PORTB.3 = 1
PAUSEUS 139
PORTB.3 = 0
PORTB.2 = 1
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF
END

Bruce
- 26th February 2005, 08:25
There is no INTCON1 register. That would be why you get the error. Look at your datasheet.

To monitor interrupt "flag bits" you do not need to enable any interrupt enable bits or global interrupts.

Any event or condition that will trigger the interrupt, will set the interrupts flag bit. This happens regardless of whether you have "any" interrupt enabled or disabled.

A "Flag bit" indicates that an interrupt event occurred.

The interrupt "Enable bit" allows program execution to branch to the interrupt vector address (if global interrupts are enabled) when the flag bit is set by the event that caused the interrupt.

You can setup the RB0/INT0 on the 18F4520 to set the interrupt flag bit on a low-to-high or high-to-low transition on RB0/INT0. See the datasheet under INTCON2.

Then all you need to do is monitor INTCON.1 (this means INTCON register bit #1 NOT INTCON1) which is the "flag bit" inidicating the transition (event) on RB0/INT0 has occured.

After reading this bit, then reset it (clear it to 0) so you can check it again later to see if the event has happend again.

TurboLS
- 26th February 2005, 16:07
OK, I checked the manual and bit 6 controls the external 0 flag. I set it to '1' for the rising edge.

INTCON2 = %0100000 ' External Interrupt Flag on Rising Edge

Do I have to set the PORTB pull up enable bit?

Also, RB0 will be read as an input (wired from the HWPM pin 17), so I will have to reconfigure my TRISB register to accept an input on PORTB, right?

thanks again for the help.

Bruce
- 26th February 2005, 16:49
Yes. You definitely need to make RB0/INT0 an input first.

Any time you make a pin an input, then you'll want to hold that pin at logic 1 or 0 through a pull-up or pull-down resistor or some "constant" external logic.

With the hardware PWM output pin connected to the RB0/INT0 input, you could possibly get by without the pull-up or pull-down, but it's cheap insurance that could save you a lot of head-scratching down the road.

A floating input will return random logic values when read, which will cause major problems. Especially with the pin configured as an interrupt source triggered by logic transitions.

If there's any chance that the external pin or device providing the interrupt logic input could be disconnected or go to a high-impedance state, then the pull-up or pull-down resistor is essential.

I always use one. If the interrupt logic is configured to trigger on a high-to-low transition, then I use a pull-up, and let the external signal provide the low-going trigger pulse. If it's setup for low-to-high transitions, then I use a pull-down resistor.

TurboLS
- 26th February 2005, 19:12
What is a good value to use for the pull-down resistor? And if I understand your logic, I shouldn't need the pull-up enable bit (bit 7) on either. So all I should have to do is leave INTCON2 as is and change TRISB to %00000001, right?

Bruce
- 26th February 2005, 20:19
I normally use 10K or > for pull-up/pull-downs, but pretty much any high value will work.

For INTCON2, you only need to worry about bit 6 INTEDG0: External Interrupt 0 Edge Select bit, and yes, you want to set the pin to an input.

TurboLS
- 26th February 2005, 20:50
So I should bridge pin 17 and PORTB.0 with a 10k resistor? or do I run it to ground? or what?

Bruce
- 26th February 2005, 23:30
You might also want to consider a series resistor between your PWM output pin & RB0/INT0 *just in case*.

If you're new to all this, the series resistor can keep you from blowing an I/O-pin while tinkering. If you
accidentally make both pins an output, this resistor can save your bacon.


pull-down
1K
RB0----------|-/\/\/\/\--PWM pin
| 10K pull-down
|--/\/\/\/\----GND

or pull-up
1K
RB0----------|-/\/\/\/\--PWM pin
| 10K pull-up
|--/\/\/\/\----+5V

TurboLS
- 26th February 2005, 23:34
thanks. I'll try that and let you know how it goes.

TurboLS
- 1st March 2005, 17:18
OK, I got a chance to test it today and neither the HWPM nor the +5V trigger to PORTA.2 work. I implemented those changes you suggested and still it doesn't work. Any ideas?

mister_e
- 1st March 2005, 17:25
can you post your current code?

TurboLS
- 1st March 2005, 17:35
' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Reset Clock
' PORTB.1 is the Vphase1 clock
' PORTB.2 is the Vphase2 clock
' PORTB.3 is the Hphase1 clock
' PORTB.4 is the Hphase2 clock
' The reset will be connected to a HWPM clock pin #17, USE FEEDBACK WIRE!!
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz
Define ADC_CLOCK 4 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

HPWM 1,64,3600 ' Supposed to send HPWM 3.6KHZ at 25% duty
INTCON2 = %0100000 ' External Interrupt on Rising Edge
INTCON.7 = 0 ' Disables global interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001101 ' Set PORTA analog, except for pin 2
TRISB = %00000001 ' Set PORTB to all output, except for bit 0
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.1 = 0
PORTB.2 = 0
PORTB.3 = 1
PORTB.4 = 0

buttonloop:
IF PORTA.2 = 1 then
GOTO vertloop
else
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.1 = 1
PAUSEUS 139
PORTB.1 = 0
PORTB.2 = 1
PAUSEUS 139
PORTB.1 = 1
PORTB.2 = 0
PAUSEUS 139
PORTB.1 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF
horizloop:
INTCON.1 = 0 ' Resets interrupt flag to 0
Resetcheck: ' Loops back to make sure
' the PORTB.3 goes low and
IF INTCON.1 = 0 THEN ' PORTB.4 goes high as close
GOTO Resetcheck ' to the external trigger's
ELSE ' rising edge as possible
ENDIF
PORTB.3 = 0
PORTB.4 = 1
PAUSEUS 139
PORTB.4 = 0
PORTB.3 = 1
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF
END

mister_e
- 1st March 2005, 18:43
about this section


vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF
horizloop:


seems to be a common used here to exit from a IF THEN statement... sorry that's a bad practice IMHO and can overflow the stack really fast.



vertpulse = vertpulse + 1
IF vertpulse >= 512 THEN buttonloop

horizloop:


about this


IF INTCON.1 = 0 THEN ' PORTB.4 goes high as close
GOTO Resetcheck ' to the external trigger's
ELSE ' rising edge as possible
ENDIF


copy/paste error !?! something missing between ELSE and ENDIF ?!?

For HPWM... looks that you'll have to do it manually... the following is an example for a PIC18F2320



' PIC18F2320
TRISC.2=0 ' CCP1 AS OUTPUT
Tmr2dutyvar VAR WORD
Tmr2dutyvar=86 ' ((1/3600)/4)/20Mhz / 16(prescaller)
PR2=$57 ' load frequency period (PWM freq=3.6 KHZ)
'set Duty cycle
CCP1CON.5=Tmr2dutyvar.1
CCP1CON.4=Tmr2dutyvar.0
CCPR1L =(tmr2dutyvar>>2)

T2CON=%00000110 ' start timer 2
' set prescaler = 16

CCP1CON = %00001100 ' pwm mode for CCP1
HERE: GOTO HERE

TurboLS
- 1st March 2005, 18:52
Is there something wrong with the HWPM command that I used? And I suppose if I take out the ELSE statement in the reset check loop, and go straight to ENDIF, then that would fix a logical error. Is my ADCON1 register set correctly to receive a digital input on PORTA.2? Also, using your clock example, would that program ever advance past the "HERE" line? The whole idea of doing the HWPM was so it would run in the background while the loops were dependant on certain conditions. thanks for the help.

mister_e
- 1st March 2005, 19:06
yes for sure Here: goto here can be skip. just for testing purpose on a single task.

once you start the PWM it will run as long as you have power on the PIC.. DEUH!!!

For the HPWM statement... i always set register myself. Never tested this one. By the book it's suppose to work... or i'm missing something like a DEFINE something stuff.

TurboLS
- 2nd March 2005, 01:26
Alright, I'll try that tomorrow and let you know how it goes. thanks again.

TurboLS
- 2nd March 2005, 15:44
OK, I tried it and I am getting the same problem. CCP1 does not appear to be oscillating at all. Also, do I have to set PORTA.2 to receive an external interrupt?? I thought if I just test and see if it has a 5V source on it, that would suffice, but maybe not. I just plopped your code example in there to see if it would compile, and it did, but does not appear to generate the desired function.

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Reset Clock
' PORTB.1 is the Vphase1 clock
' PORTB.2 is the Vphase2 clock
' PORTB.3 is the Hphase1 clock
' PORTB.4 is the Hphase2 clock
' The reset will be connected to a HWPM clock pin #17, USE FEEDBACK WIRE!!
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz
Define ADC_CLOCK 4 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

' PIC18F2320 example, may need to change
TRISC.2=0 ' CCP1 AS OUTPUT
Tmr2dutyvar VAR WORD
Tmr2dutyvar=86 ' ((1/3600)/4)/20Mhz / 16(prescaller)
PR2=$57 ' load frequency period (PWM freq=3.6 KHZ)
'set Duty cycle
CCP1CON.5=Tmr2dutyvar.1
CCP1CON.4=Tmr2dutyvar.0
CCPR1L =(tmr2dutyvar>>2)

T2CON=%00000110 ' start timer 2
' set prescaler = 16

CCP1CON = %00001100 ' pwm mode for CCP1

INTCON2 = %0100000 ' External Interrupt on Rising Edge
INTCON.7 = 0 ' Disables global interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001101 ' Set PORTA analog, except for pin 2
TRISB = %00000001 ' Set PORTB to all output, except for bit 0
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.1 = 0
PORTB.2 = 0
PORTB.3 = 1
PORTB.4 = 0

buttonloop:
IF PORTA.2 = 1 then
GOTO vertloop
else
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.1 = 1
PAUSEUS 139
PORTB.1 = 0
PORTB.2 = 1
PAUSEUS 139
PORTB.1 = 1
PORTB.2 = 0
PAUSEUS 139
PORTB.1 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
GOTO buttonloop
ENDIF
horizloop:
INTCON.1 = 0 ' Resets interrupt flag to 0
Resetcheck: ' Loops back to make sure
' the PORTB.3 goes low and
IF INTCON.1 = 0 THEN ' PORTB.4 goes high as close
GOTO Resetcheck ' to the external trigger's
' rising edge as possible
ENDIF
PORTB.3 = 0
PORTB.4 = 1
PAUSEUS 139
PORTB.4 = 0
PORTB.3 = 1
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16416,[BIN8 adval,13,10] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF
END

mister_e
- 2nd March 2005, 16:01
mm, unfortunately i don't have any of those 4520 here to test... weird.

Did you set config fuse to HS oscillator in your programmer?!?
is your MCLR is tie to VCC via 1K-10K resistor ?!?
is your supply line 5volts and clean... have you place 0.1 uF close to the PIC?!?
Is a stupid blink light on this pin work?!?

TurboLS
- 2nd March 2005, 16:11
Yes, I have HS configured in the EPIC programmer.

My master clear is tied to +5V through a 1k resistor.

My supply line is 5V.

And I was doing a lot more than the blinking program on this PIC before I tried doing the HPWM.

TurboLS
- 2nd March 2005, 16:22
It wouldn't have anything to do with my DEFINE ADC_CLOCK line, would it?

Bruce
- 2nd March 2005, 17:03
When you're having problems like this, it's sometimes much easier to simplify
everything & start with a single peice of code that gets a peripheral you're
having problems with working first.

Then move on to testing your other routines step-by-step, inserting tested
& known working code with new code until you hit the problem again. Then
you at least have some idea of what may be causing the problem.

Try something like this without any other code to test your CCP module.
Disconnect all external circuits just in case it's an external circuit connection
that causing problems.



DEFINE HPWM1_TIMER 2
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2 ' RC2
DEFINE HPWM2_TIMER 2
DEFINE CCP2_REG PORTC
DEFINE CCP2_BIT 1 ' RC1

TRISC.1 = 0
TRISC.2 = 0 ' HPWM automatically does this for you, but just in case
CCP1CON = %00001100 ' PWM mode
CCP2CON = %00001100 ' PWM mode

HPWM 1,127,3600 ' RC2/CCP1 3.6kHz @ ~50% duty
HPWM 2,127,3600 ' RC1/CCP2 3.6kHz @ ~50% duty

Does it work?

If it does, then you have verified your CCP module & PBP code to control
it. If it doesn't work then you may have a hardware or config problem.

Your PBP device header file (18F4520.INC) has "deafult" config fuse settings
in it something like the following;


INCLUDE "P18F4520.INC" ; MPASM Header
__CONFIG _CONFIG1H, _OSC_XT_1H
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_128_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L

If you think maybe your programmer isn't setting HS when selected manually,
then edit your inc file changing XT in the first line to HS. Save it, close it,
and re-compile. Then check to see if it's really set to HS when you open the
.HEX file with your programmer before programming your 4520.

Once you get hardware PWM working, then move on to insert other code
modules one-by-one, and re-test.

TurboLS
- 2nd March 2005, 18:03
Thanks again for your input. I will definitely try that and let you guys know what happens.

Oh, and I checked on the .INC file and the folder with this software doesn't come with any of the 18 series include files. I guess that could be a major problem. I am looking in the PBP/INC directory in case I should be looking somewhere else.

TurboLS
- 2nd March 2005, 18:25
OK, I tried your HPWM test code and I do get a clock, however the Oscope says it is running at 18.15kHz, not 3.6kHz. Any ideas??

TurboLS
- 2nd March 2005, 18:37
OK, now this is weird.

I put the exact same code into my program and now it reads 3.6kHz. In addition, it only reads correctly if I don't have those resistors between RB0 and CCP1. When they are in, the frequency goes to 0. Am I overloading the timer or something? Anyway, I am going to try and see if I can take out those resistors and see if my program will run with the PORTA.2 touching the 5V. thanks again.

TurboLS
- 2nd March 2005, 18:55
OK, it seems to work fine when I don't have the CCP1 pin connected to the RB0 pin, which I guess means that I have my interrupt somehow coded wrong. I thought that I had the TRISB register set correctly to all outputs except for PORTB.0

mister_e
- 3rd March 2005, 03:23
mmm, are you saying PWM stops when you jump CCP1 to RB0? what about if you do a simple blink on this RB0 pin... or do a simple IF THEN on RB0

IF PORTB.0 = 1 then DoSomething or Start HPWM

maybe this pin is burn now :(

TurboLS
- 3rd March 2005, 03:37
So you are saying that my code is right and the pin is just acting weird? If it is burned, I have like 8 more PIC chips. I just want to make sure that the problem is fixed before I burn another one. So I will test this PORTB.0 with a simple blink program to see if it responds at all. I'll let you know what happens. Thanks again for your continued input.

mister_e
- 3rd March 2005, 03:39
Do the RB0 test before using others.

BTW, i'm about setting up a board to do something like this for testing. ì'll post the code here.

mister_e
- 3rd March 2005, 04:23
This one use RB0 interrupt handler routine.



' INT0 with PWM
' =============
'
' File name : INT0_PWM.bas
' Company : Mister E
' Programmer : Steve Monfette
' Date : 02/03/2005
' Device : PIC18F2320
'
'
' This program generate 3.6Khz @ 25% duty PWM on CCP1 pin.
'
' CCP1 pin is connected to RB0 pin via 1k resistor.
'
' Program blink a led on PORTB.6 while generating PWM.
' Each rising edge of PWM, PORTB.7 is toggle. This will
' generate 1.8Khz 50% duty on this PORTB.7 pin.
'
' We will use Interrupt on RB0(INT0) pin to detect rising edge


' Hardware Definition
' ===================
'
DEFINE LOADER_USED 1
DEFINE OSC 20

TRISB=%00000001 ' PORTB.0 as input
TRISC.2=0 ' PORTC as output
ADCON1=$0F ' disable A/D converter

' Interrupt definition
' ====================
'
INTCON=%10010000 ' Enable global interrupt
' Enable INT0 interrupt (RB0)

INTCON2.6=1 ' Enable INT0 on rising edge

ON interrupt goto RB0_interrupt

' Variable definition
' ===================
'
Tmr2dutyvar VAR WORD
DelayLoop var word

' PWM signal generation
' =====================
'

Tmr2dutyvar=86 ' load duty time duration
PR2=$57 ' load frequency period (PWM freq=3.6 KHZ)

' set Duty cycle
' --------------
'
CCP1CON.5=Tmr2dutyvar.1
CCP1CON.4=Tmr2dutyvar.0
CCPR1L =(tmr2dutyvar>>2)

T2CON=%00000110 ' start timer 2
' set prescaler = 16

CCP1CON = %00001100 ' pwm mode for CCP1


' Main Loop
' =========
'
' Stupid led blink on PORTB.6...
'
Start:
toggle PORTB.6
for delayloop = 1 to 50000
pauseus 5
next
goto start


' Interrupt routine
' =================
'
' toggle PORTB.6 each rising edge on it.
'
disable
RB0_interrupt:
toggle PORTB.7
INTCON.1=0 ' reset INT0 interrupt flag
resume
enable

mister_e
- 3rd March 2005, 04:31
By polling INT0 flag bit... no interrupt handler



' INT0 polling with PWM
' =====================
'
' File name : INT0_poll_PWM.bas
' Company : Mister E
' Programmer : Steve Monfette
' Date : 02/03/2005
' Device : PIC18F2320
'
'
' This program generate 3.6Khz @ 25% duty PWM on CCP1 pin.
'
' CCP1 pin is connected to RB0 pin via 1k resistor.
'
' Program blink a led on PORTB.6 while generating PWM.
' Each rising edge of PWM, PORTB.7 is toggle. This will
' generate 1.8Khz 50% duty on this PORTB.7 pin.
'
' We will check INTCON.1 (Interrupt on RB0(INT0) flag bit) pin to
' detect rising edge


' Hardware Definition
' ===================
'
DEFINE LOADER_USED 1
DEFINE OSC 20

TRISB=%00000001 ' PORTB.0 as input
TRISC.2=0 ' PORTC as output
ADCON1=$0F ' disable A/D converter

' Interrupt definition
' ====================
'
INTCON=%00010000 ' Disable global interrupts
' Enable INT0 interrupt (RB0)

INTCON2.6=1 ' Enable INT0 on rising edge


' Variable definition
' ===================
'
Tmr2dutyvar VAR WORD
DelayLoop var word

' PWM signal generation
' =====================
'

Tmr2dutyvar=86 ' load duty time duration
PR2=$57 ' load frequency period (PWM freq=3.6 KHZ)

' set Duty cycle
' --------------
'
CCP1CON.5=Tmr2dutyvar.1
CCP1CON.4=Tmr2dutyvar.0
CCPR1L =(tmr2dutyvar>>2)

T2CON=%00000110 ' start timer 2
' set prescaler = 16

CCP1CON = %00001100 ' pwm mode for CCP1


' Main Loop
' =========
'
' Stupid led blink on PORTB.6 while testing INT0 flag bit
'
Start:
toggle PORTB.6
for delayloop = 1 to 50000
pauseus 5
if INTCON.1 then
INTCON.1=0
toggle PORTB.7
endif

next
goto start

TurboLS
- 4th March 2005, 03:35
Is there any reason why I can't get the process to start when PORTA.2 goes high?? I haven't rewired the HPWM/RB0 yet, but that should not matter. The PIC should at least shift the vertical clocks before even checking the reset (interrupt flag). Are my registers set correctly for analog input to PORTA.0 and digital input to PORTA.2??

mister_e
- 4th March 2005, 04:01
to have analog on PORTA.0

ADCON1=%00001110

TurboLS
- 5th March 2005, 03:15
OK, well I think I got it working so that it waits for the push button to start, but then it seems like it keeps going even after the loops have completed. I will put in an LED command to signal when clocking is in progress and see what happens. It may just be that my calculations for transfer times are just off. I figured that at 3.6Khz sampling (which is how fast we would be sampling the real data), we could sample the data, do the A/D, and send the data off chip in about 2 minutes at 19200 inverted baud. Am I off in my estimations?

TurboLS
- 5th March 2005, 15:22
Again, I have about 350,000 samples to take and transfer off the PIC serially.

TurboLS
- 8th March 2005, 03:00
OK, I think I finally have everything working. I have an LED on bit 5 of portb the is low when the clocks are not running and hig when they are. I had had a problem with the switch on PORTA.2 floating high, so I put a 2 position switch between 5v and ground and that seemed to solve the problems. My next move is to hook up a logic analyzer to make sure all the clocks are synched up. Thanks guys for all your help and I'll let you know how it goes.

mister_e
- 8th March 2005, 03:40
you don't really need that kind of switch.... place a pull-up or pull down resistor will do the job as well.

For the logic analyser stuff... great idea if you have one. Case not, if you still have an analog scope, it's easy to build one with few CMOS components.

TurboLS
- 8th March 2005, 04:53
We have a DigiView in the lab. I have never used one, so I am gonna take a few hours one day just to learn the ropes. But yeah, I definitely have one to work with. Also, since this is a camera, I think a physical button was the way to go, since, down the road, we want to make this thing hand held.

TurboLS
- 9th March 2005, 21:14
OK, I think I realized why my data is taking so long to transfer. It is because the PIC is sending the character representations of 1's and 0's, which are 49's and 48's. Is there a way to send out true binary data? (Matlab picks up the 48's and 49's which is how i figured the whole thing out.) thanks.

TurboLS
- 10th March 2005, 21:38
OK, I have increased the baud rate to 38,400 baud. I have exactly 407,680 8 bit samples to take. I am sampling at about 3.6kHz. How long do you think it should take to sample the data, do the A/D conversion, and send it off chip serially at these speeds?

Here are my time calculations:

407680 samples = 3261440 true bits of data. However, since the PIC can only send out the ASCII representation of the formats I want (mainly decimal and binary), each number (the 2 in 255 for example) requires 5 bits to store since the decimal value of the character '2' is 50. So technically, each bit of data sampled on the PIC requires 5 bits to transfer. So I estimated that since there are 5 bits to send for each bit sampled, the total amount of data to transmit is 16,307,200 bits. So, if the data were already on chip, it would take about 8 minutes to get it all out. Then I added the amount of time it takes to sample the data, which is about 3 minutes (with slack) and so the whole thing should take around 10 minutes, right? Wrong, hyperterminal has been reading data for over a half hour and is still going. Should I use a faster sampling rate since I can now send data out at 38,400 baud? Am I overloading the stack? I don't know.

thanks for any input.

TurboLS
- 14th March 2005, 20:21
OK, we got the logic analyzer working and I think some of the commands are taking a lot longer than I had expected.

The horizontals are not even close to 50% duty cycle as one is high for 960 usec and low for 140usec (the other horizontal is opposite). I was shooting for more in the neighborhood of 140usec for both the high and low for both clocks. In addition, I can't seem to see the vertical on the logic analyzer at all. Maybe i need to adjust some settings, but I'm gettin kinda worried.

thanks for all the help.

My updated code is below:

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Reset Clock
' PORTB.1 is the Vphase1 clock
' PORTB.2 is the Vphase2 clock
' PORTB.3 is the Hphase1 clock
' PORTB.4 is the Hphase2 clock
' The reset will be connected to a HWPM clock pin #17, USE FEEDBACK WIRE!!
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz


' Define HPWM parameters
DEFINE HPWM1_TIMER 2
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2 ' RC2

TRISC.1 = 0 ' HPWM automatically does this for you, but just in case
CCP1CON = %00001100 ' PWM mode

HPWM 1,127,3600 ' RC2/CCP1 3.6kHz @ ~50% duty

' Define interrupt parameters
INTCON2 = %01000000 ' External Interrupt on Rising Edge
INTCON.7 = 0 ' Disables global interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001110 ' Set PORTA digital, except for bit 0
TRISB = %00000001 ' Set PORTB to all output, except for bit 0
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.1 = 0
PORTB.2 = 0
PORTB.3 = 1
PORTB.4 = 0
PORTB.5 = 0 ' LED off indicates that the camera is not transferring data

buttonloop:
IF PORTA.2 = 1 then
PORTB.5 = 1
GOTO vertloop
else
PORTB.5 = 0
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.1 = 1
PAUSEUS 139
PORTB.1 = 0
PORTB.2 = 1
PAUSEUS 139
PORTB.1 = 1
PORTB.2 = 0
PAUSEUS 139
PORTB.1 = 0
PAUSEUS 270
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
PORTB.5 = 0
GOTO buttonloop
ENDIF
horizloop:
INTCON.1 = 0 ' Resets interrupt flag to 0
Resetcheck: ' Loops back to make sure the PORTB.3 goes low and
IF INTCON.1 = 0 THEN ' PORTB.4 goes high as close
GOTO Resetcheck ' to the external trigger's rising edge as possible
ENDIF
PORTB.3 = 0
PORTB.4 = 1
PAUSEUS 139
PORTB.4 = 0
PORTB.3 = 1
PAUSEUS 15
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
SEROUT2 PORTC.6,16390,[DEC adval] ' Output 8 bit word serially to PC from C.6
PAUSEUS 87
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 270
GOTO vertloop
ENDIF
END

TurboLS
- 14th March 2005, 21:28
OK, so I commented out the serout2 line and now the high time is 140 usec and the low is 420usec. I think this means that the serout2 command line is taking 540usec to execute for some reason. Is there any reason for this?? Can I speed it up??

After i did that test, I commented out the pauseus 15 and pauseus 87 in addition to the serout2 and it was almost perfect high 150 usec and low 140 usec. The weird part is that i have pauses for the high, but none for the low and they are still in synch. So, yeah basically the serout2 command is taking for ever.

mister_e
- 15th March 2005, 00:14
use HSEROUT or access direct to the internal USART registers. SERIN/SEROUT and others are good when your PIC don't have any internal USART OR when you want to use multiples serial i/o's

@20MHZ you'll be able to use higher baudrate than with the PBP statements.

TurboLS
- 15th March 2005, 02:37
Well it's not the baud rate that i slowing it down (or atleast not as much), it's the time it takes to run through the command. I suppose I could just see if I could slow the clocks down so that I could still maintain 50% duty cycle. Also, how fast do the HSEROUT commands take to execute? because the baudrate will not make much of a difference if I run into the same issue of execution time as I do with the SEROUT2 command.

TurboLS
- 15th March 2005, 14:21
Also, what if I just send the character representation of the 8-bit sample? Then Matlab could convert that into a decimal on the PC. Then every byte of true data would be sent as 1 byte, not 8 bytes. I am going to mess around with different configurations of the serout2 command to see if there is any change in the execution times.

In addition, what is the general convention for estimating the frequency on the HPWM clock? like if i wanted it to go slower, would i use a smaller number?

TurboLS
- 15th March 2005, 17:59
OK, did some more testing today. Here are the results:

with the ADCIN 0 line and the SEROUT2 PORTC.6,16390,[adval] line, the high time was 410usec, which i suppose is better than 540usec from before. So I wrote the HPWM as follows:

HPWM 1,31,1221

now the reset and the horizontals work fine, but it appears that whenever the HPWM is running, the verticals don't. Can anyone explain this to me? thanks.

TurboLS
- 15th March 2005, 18:44
I also tried the HSEROUT commands and I could get the command to execute faster, however, I think I am trying to receive from the wrong port. I have C.6 wired to the PC and nothing is coming in. In fact, Hyperterminal says it can't even open the port. Also, I looked at the Logic Analyzer output with this new command structure (i mean HSEROUT instead of SEROUT2) and it appears that the H1 and H2 are exactly in phase, instead of the 180 degrees out of phase which they should be. Below is my updated code, notice the commands that show B.3 and B.4 are opposite:

' Connect analog input to (RA0)
' Connect clocks to PORTB
' PORTB.0 is the Reset Clock
' PORTB.1 is the Vphase1 clock
' PORTB.2 is the Vphase2 clock
' PORTB.3 is the Hphase1 clock
' PORTB.4 is the Hphase2 clock
' The reset will be connected to a HWPM clock pin #17, USE FEEDBACK WIRE!!
' Connect pin 2 from the DB9 connector to PORTC.6
' Have a +5V source ready to touch PORTA.2 to trigger clocking process

include "modedefs.bas"

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
DEFINE OSC 20 ' Sets clock speed to 20Mhz

' Define HSEROUT parameters
DEFINE HSER_TXSTA 24h ' High speed baud generator
DEFINE HSER_BAUD 57600 ' 57600 baud rate


' Define HPWM parameters
DEFINE HPWM1_TIMER 2
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2 ' RC2

TRISC.1 = 0 ' HPWM automatically does this for you, but just in case
CCP1CON = %00001100 ' PWM mode

HPWM 1,31,3600 ' RC2/CCP1 3.6kHz @ ~1/8% duty

' Define interrupt parameters
INTCON2 = %01000000 ' External Interrupt on Rising Edge
INTCON.7 = 0 ' Disables global interrupts
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00001110 ' Set PORTA digital, except for bit 0
TRISB = %00000001 ' Set PORTB to all output, except for bit 0
Pause 500 ' Wait .5 second
Pause 500 ' Wait .5 second

horizpulse var byte
vertpulse var byte
adval var byte ' Create adval to store result

horizpulse = 1 ' Initialize counters, initial states
vertpulse = 1
PORTB.1 = 0
PORTB.2 = 0
PORTB.3 = 1
PORTB.4 = 0
PORTB.5 = 0 ' LED off indicates that the camera is not transferring data

buttonloop:
IF PORTA.2 = 1 then
PORTB.5 = 1
GOTO vertloop
else
PORTB.5 = 0
GOTO buttonloop ' Waits for 5V that signals shutter is closed
ENDIF
vertloop:
horizpulse = 1
PORTB.1 = 1
PAUSEUS 280
PORTB.1 = 0
PORTB.2 = 1
PAUSEUS 280
PORTB.1 = 1
PORTB.2 = 0
PAUSEUS 280
PORTB.1 = 0
PAUSEUS 820
vertpulse = vertpulse + 1
IF vertpulse < 512 THEN
GOTO horizloop
ELSE
PORTB.5 = 0
GOTO buttonloop
ENDIF
horizloop:
INTCON.1 = 0 ' Resets interrupt flag to 0
Resetcheck: ' Loops back to make sure the PORTB.3 goes low and
IF INTCON.1 = 0 THEN ' PORTB.4 goes high as close
GOTO Resetcheck ' to the external trigger's rising edge as possible
ENDIF
PORTB.3 = 0
PORTB.4 = 1
PAUSEUS 140
PORTB.4 = 0
PORTB.3 = 1
ADCIN 0, adval ' A/D 8 bit value from PORTA.0 into adval
HSEROUT [adval] ' Output ASCII character rep of word serially to PC from C.6
horizpulse = horizpulse + 1
IF horizpulse < 784 THEN
GOTO horizloop
ELSE
PAUSEUS 820
GOTO vertloop
ENDIF
END

TurboLS
- 16th March 2005, 14:29
OK, well I figured out why I was getting weird readings on the logic analyzer... I was looking at the wrong (duplicate) channels, which is why I thought they (h1 and h2 and v1 and v2) were in phase instead of 180 degrees out of phase. So they work fine. Now, I think my only problem is that the chip cannot stop... It will wait for me to push the button on PORTB.5, but even after like 10 minutes, it will not stop (total time for transfer calculated to be about 2.5 minutes). Is there any reason why the loop structure would not be working?? Are the values to big for the stack (the counters i mean)? thanks again.