View previous topic :: View next topic |
Author |
Message |
bcs99
Joined: 22 Nov 2003 Posts: 32
|
syncronization problem |
Posted: Tue Aug 02, 2005 8:49 pm |
|
|
I have a circuit that uses a PIC1F688 using the internal 8Mhz oscillator. It has two 5Khz PWM inputs (RA4 and RA5). These inputs are independent and are either off or driven with a 25-75% duty cycle. The input PWM is to be mirrored out (RA2 and RC0) when no error condition is present. Two ADC inputs (RC2 and RC1) are are used to monitor current flow. There are two current SENSE signal outputs (RC4 and RC5) that are to be set when current is present on the ADC inputs. Also there is an ERROR signal output (RC3) that is to be set when an overcurrent condition has occurred.
I'm having trouble syncronizing everything that needs to be done. The ADC inputs need to read and tested at regular intervals syncronized with the PWM (or a timer when the PWM is not present) and the PWM needs to be mirrored. The only consistent time available is at the beginning and end of the PWM cycle when the output is either high (1-25%) or low (76-100%). Each about 50us or 100 clock cycles.
The code below my latest attempt at it. It only works in bursts suggesting that there is a timing problem.
Thanks in advance.
Bob
Code: |
#CASE // compiler is case sensitive
#include <16F688.h> // using the PIC16F688
#DEVICE ADC=8 // using 8 bit ADC
#FUSES NOWDT, INTRC_IO, BROWNOUT, MCLR, NOCPD, NOPUT, NOIESO, NOFCMEN
#USE delay(clock=8000000) // internal clock at 8Mhz
#USE FAST_IO( A ) // ports won't change
#USE FAST_IO( C ) // so use fast access
#BYTE PORTA = 0x105 // direct port A access
#BYTE PORTC = 0x107 // direct port C access
#BIT ERROR = PORTC.3 // direct crowbar error output
#BIT SENSE_1 = PORTC.4 // direct #1 sense output
#BIT SENSE_2 = PORTC.5 // direct #2 sense output
#BIT IN_1 = PORTA.5 // direct #1 pwm input
#BIT IN_2 = PORTA.4 // direct #2 pwm input
#BIT OUT_1 = PORTA.2 // direct #1 pwm output
#BIT OUT_2 = PORTC.0 // direct #2 pwm output
#define SENSE 2
#define CROWBAR 20
void main()
{
static int index, reading, timer;
set_tris_a( 0b00111000 ); // setup port a
set_tris_c( 0b00000110 ); // setup port c
OUT_1 = OUT_2 = FALSE; // no drive to start
SENSE_1 = SENSE_2 = 0; // no current to start
ERROR = 0; // no error to start
setup_oscillator( OSC_8MHZ ); // use internal 8Mhz clock
setup_adc_ports( sAN5 | sAN6 | VSS_VDD ); // setup ADC
setup_adc( ADC_CLOCK_INTERNAL ); // using internal clock
setup_comparator(NC_NC_NC_NC); // no comparators
setup_counters( RTCC_INTERNAL, RTCC_DIV_2 ); // 256us overflow
setup_timer_1( T1_DISABLED ); // timer 1 not used
set_adc_channel( 5 ); // set initial channel
delay_ms( 1000 ); // wait for driver
set_rtcc( 0 ); // sync timer
while( TRUE )
{
while( get_rtcc() < 200 ) // syncronize on timer
{
if( IN_1 == TRUE || IN_2 == TRUE ) // test PWM input
{
break; // syncronize on PWM
}
}
set_rtcc( 0 ); // reset timer
if( ERROR == FALSE ) // start if no errors
{
if( IN_1 == TRUE ) OUT_1 = TRUE; // turn on pwm outputs
if( IN_2 == TRUE ) OUT_2 = TRUE;
}
read_adc( ADC_START_ONLY ); // start adc reading
while( get_rtcc() < 50 ); // wait for 25% duty
reading = read_adc( ADC_READ_ONLY ); // finish adc reading
while( get_rtcc() < 150 ) // watch pwm to 75%
{
if( ERROR == FALSE ) // stop when no errors
{
if( OUT_1 != IN_1 ) OUT_1 = FALSE; // turn off pwm outputs
if( OUT_2 != IN_2 ) OUT_2 = FALSE;
}
}
if( ERROR == FALSE ) // stop when no errors
{
if( OUT_1 == TRUE ) OUT_1 = FALSE; // turn off pwm outputs
if( OUT_2 == TRUE ) OUT_2 = FALSE;
}
ERROR = (reading > CROWBAR); // test reading for error
if( index == 1 ) // which index?
{
SENSE_1 = (reading > SENSE); // set sense output
set_adc_channel( 6 ); // set adc channel
index = 0; // set index
}
else
{
SENSE_2 = (reading > SENSE); // set sense output
set_adc_channel( 5 ); // set adc channel
index = 1; // set index
}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 02, 2005 11:38 pm |
|
|
I didn't try to solve your overall problem. I just looked at things that seemed strange to me.
Here you're defining the port registers in RAM Bank 2:
Quote: | #BYTE PORTA = 0x105 // direct port A access
#BYTE PORTC = 0x107 // direct port C access |
They are also available in Bank 0, and it would save a lot of
bank switching code if you put them there. Like this:
Code: | #BYTE PORTA = 0x5
#BYTE PORTC = 0x7 |
I made that change and re-compiled your code. The ROM usage
went from 271 words down to 231. That's with PCM vs. 3.230.
There are three places where you've got code similar to this:
Quote: | ERROR = (reading > CROWBAR); |
If you change it to look like this (in all three places) your ROM usage
goes down to 213 words.
Code: |
if(reading > CROWBAR)
ERROR = TRUE;
else
ERROR = FALSE; |
So if part of your problem is caused by slow speed of execution,
doing these changes will help. |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Wed Aug 03, 2005 10:17 am |
|
|
I was surprised when you said these compile differently.
Code: | ERROR = (reading > CROWBAR); |
Code: |
if(reading > CROWBAR)
ERROR = TRUE;
else
ERROR = FALSE; |
In an older versions of the compiler (3.184) they compile the same. In 3.221 the if statement is optimized but the logical assignment is not. For the PIC18 series they are the same in both compilers versions.
Last edited by Neutone on Wed Aug 03, 2005 2:45 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 03, 2005 11:51 am |
|
|
This was compiled with PCM vs. 3.230. In the first method,
the compiler is putting the result of the expression into an
intermediate variable. This takes several extra lines of code.
The default optimization level was used. Changing it to #opt 11
or 9, or 5 has no effect.
Code: | 0000 00482.. ERROR = (reading > CROWBAR); // test reading for error
00AC 0823 00483 MOVF 23,W
00AD 3C14 00484 SUBLW 14
00AE 1C03 00485 BTFSS 03.0
00AF 28B2 00486 GOTO 0B2
00B0 3000 00487 MOVLW 00
00B1 28B3 00488 GOTO 0B3
00B2 3001 00489 MOVLW 01
00B3 00A1 00490 MOVWF 21
00B4 1821 00491 BTFSC 21.0
00B5 28B8 00492 GOTO 0B8
00B6 1187 00493 BCF 07.3
00B7 28B9 00494 GOTO 0B9
00B8 1587 00495 BSF 07.3 |
Code: | 0000 00484 .................... if(reading > CROWBAR)
00AC 0823 00485 MOVF 23,W
00AD 3C14 00486 SUBLW 14
00AE 1803 00487 BTFSC 03.0
00AF 28B2 00488 GOTO 0B2
0000 00489 .................... ERROR = TRUE;
00B0 1587 00490 BSF 07.3
0000 00491 .................... else
00B1 28B3 00492 GOTO 0B3
0000 00493 .................... ERROR = FALSE;
00B2 1187 00494 BCF 07.3 |
Here is the same code compiled with PCM vs. 3.188.
It's much smaller.
Code: |
0000 00506...ERROR = (reading > CROWBAR); // test reading for error
00C8 0823 00507 MOVF 23,W
00C9 3C14 00508 SUBLW 14
00CA 1C03 00509 BTFSS 03.0
00CB 28CE 00510 GOTO 0CE
00CC 1187 00511 BCF 07.3
00CD 28CF 00512 GOTO 0CF
00CE 1587 00513 BSF 07.3 |
|
|
|
|