PDA

View Full Version : Analog issue



jmgelba
- 15th March 2009, 19:56
Thought I'd figured this stuff out years ago. Anyway, here's a little program to read the voltage on a bank of capacitors and fire a pair of FETs for a period of time depending on the 1's an 0's on 4 pins.
It should not allow the FETS to fire untill the adc reading is 466 or higher. However it fires regardless of adc reading.

What gotcha did I miss?

18F1320, running on 8mhz internal osc.


OSCCON = $70 'set internal resonator to 8mhz
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
DEFINE OSC 8
BNK1 VAR WORD
BNK2 VAR WORD
DUR VAR WORD


ADCON0 = %00000001
ADCON1 = %01111100
ADCON2 = %10111111

TRISA = %11111111
TRISB = %11110000

PORTB.0 = 1
PORTB.1 = 1
PORTB.2 = 1
PORTB.3 = 0

BNK1 = 0
BNK2 = 0
DUR = 0

MAIN:
DUR = 0
PORTB.3 = 0
BNK1 = 0
BNK2 = 0
ADCIN 0, BNK1
ADCIN 1, BNK2

IF PORTB.4 = 1 THEN DUR = 8
IF PORTB.5 = 1 THEN DUR = 4
IF PORTB.6 = 1 THEN DUR = 2
IF PORTB.7 = 1 THEN DUR = 1
IF BNK1 OR BNK2 => 466 THEN FLASH
IF BNK1 OR BNK2 =< 465 THEN MAIN

FLASH:
IF PORTA.4 = 1 OR PORTA.5 = 0 THEN PORTB.3 = 1
IF PORTA.4 = 1 OR PORTA.5 = 0 THEN PORTB.0 = 0 : PORTB.1 = 0
PORTB.3 = 0
IF DUR = 1 THEN PAUSE 1
IF DUR = 2 THEN PAUSE 2
IF DUR = 4 THEN PAUSE 4
IF DUR = 8 THEN PAUSE 8
PORTB.0 = 1 : PORTB.1 = 1
PAUSE 100
GOTO MAIN

mistergh
- 15th March 2009, 22:08
where are your ENDIF's

jmgelba
- 15th March 2009, 23:41
I had end if's in there and it threw errors. Deleted and compiled fine.

mistergh
- 16th March 2009, 01:56
harr... That was the first what poked into my eye. When I copied your code into my editor (Microcode Studio), it did not compile (picbasic pro) and several error messages popped up.
What software are you using to edit, compile etc.?

Darrel Taylor
- 16th March 2009, 05:08
It should not allow the FETS to fire untill the adc reading is 466 or higher. However it fires regardless of adc reading.

Perhaps changing ...

IF BNK1 OR BNK2 => 466 THEN FLASH
IF BNK1 OR BNK2 =< 465 THEN MAIN
... to ...

IF (BNK1 => 466) OR (BNK2 => 466) THEN FLASH
GOTO MAIN

jmgelba
- 17th March 2009, 14:27
DT - Thanks, that fixed the issue.
Now, an unexpected one has appeared. First I'll explain the product.
We are looking for a 1 to 2ms pulse appearing on either porta.0 or porta.1. Upon receipt of the pulse I have to send out a 1, 2, 4 or 8ms pulse to turn on 2 FETs located at portb.0 and portb.1 The time of the pulse depends upon dipswitch settings.
So if set to 4ms, the program should scan the capacitors for the correct voltage, wait for a pulse input, fire FET's for 4ms when received, go back and wait for the next pulse in.

The problem is the FETS fire anywhere from 1 time to 6 times per one 1 ms pulse input.
I need an ultra fast reaction time so after a pulse is recieved I cant go and do other stuff before turning on the FET's.

I thought about adding a 10ms delay at the end of the flash subroutine and I've thought about adding a count. If count = 1 and there is a pulse received, I could tell it to ignore the input. The count would have to get to reset to zero in the loop somewhere.

Heres the code as it stands right now.


OSCCON = $70 'set internal resonator to 8mhz
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 5 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 20 ' Set sampling time in uS
DEFINE OSC 8
BNK1 VAR WORD
BNK2 VAR WORD
DUR VAR WORD


ADCON0 = %00000001
ADCON1 = %01111100
ADCON2 = %10111110

TRISA = %11111111
TRISB = %11110000

PORTB.0 = 1
PORTB.1 = 1
PORTB.2 = 1
PORTB.3 = 0

BNK1 = 0
BNK2 = 0
DUR = 0

MAIN:
DUR = 0
PORTB.3 = 0
BNK1 = 0
BNK2 = 0
ADCIN 0, BNK1
ADCIN 1, BNK2

IF PORTB.4 = 1 then
DUR = 8
endif
IF PORTB.5 = 1 THEN
DUR = 4
endif
IF PORTB.6 = 1 THEN
DUR = 2
endif
IF PORTB.7 = 1 THEN
DUR = 1
endif
IF (BNK1 => 466) OR (BNK2 => 466) THEN FLASH
goto MAIN




FLASH:
IF PORTA.4 = 1 OR PORTA.5 = 0 THEN
PORTB.0 = 0 : PORTB.1 = 0 : PORTB.3 = 1
endif


IF DUR = 1 THEN
PAUSE 1
endif
IF DUR = 2 THEN
PAUSE 2
endif
IF DUR = 4 THEN
PAUSE 4
endif
IF DUR = 8 THEN
PAUSE 8
endif
PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0

GOTO MAIN

Acetronics2
- 17th March 2009, 14:54
Hi, JM

That looks to be dealing with high voltage ... and very high instant currents.

May be also a switching up converter to think to ...


soooo ...

are you REALLY sure there's no spike on either an ADC input or 5v supply rails ???

could we have a piece of scheme showing the Fet's drive and the ADC inputs ???

Alain

jmgelba
- 17th March 2009, 15:13
There could be spikes - I have yet to measure for that. And yes, we are switching 2 channels, both at 760W each. 24v at 31.6 Amps.

I'd have to ask the whole forum to sign an NDA to show you the schematic, but the 5v line has a lot of capacitance but the inputs do not as I cant wait for the line to charge. From input pulse to output on needs to be less than 35uS. My customer wanted 5uS or less originally!!

Archangel
- 17th March 2009, 15:59
My customer wanted 5uS or less originally!!
Make it so . . http://www.realmagicwands.com/

jmgelba
- 17th March 2009, 16:02
Just measured for spikes - there are some small ones on the 5v line lasting in the uS range. Largest I've seen was 0.341V. ADC line is dirty. I'm sampling for 20uS. I'll put a .1uF and a 1nF on there and see what happens.

I put a 10ms delay at the end of the flash subroutine and so far that looks to be working.

Acetronics2
- 17th March 2009, 16:23
Hi,

One thing you easily can do is lock your inputs as soon as Fets fired ... you have the time the capacitors charge for gliches " hiding" ...

I'll search on my HDD ... there's an old Elektor project of a ... discharge capacitor welding machine for NiCads ...

Your application HardW should not be so far from that !!!

Alain

jmgelba
- 17th March 2009, 16:49
Hmm have a problem else where. Just to verify my 10ms delay was working, I increased it to 1000ms. Now the flash (FET's)does not respond to the input. I can send a pulse and nothing happens, then I get lucky some times. Turns out that the program is running and pausing for 1000ms as though there has been a pulse sent.

So the problem I have is it is running through the whole program and not returning to MAIN and waiting for a pulse.


IF (BNK1 => 466) OR (BNK2 => 466) THEN FLASH
goto MAIN

This should make the program jump back to the start of MAIN unless the ADC is 466 or higher, right?





FLASH:
IF PORTA.4 = 1 OR PORTA.5 = 0 THEN
PORTB.0 = 0 : PORTB.1 = 0 : PORTB.3 = 1
endif


IF DUR = 1 THEN
PAUSE 1
endif
IF DUR = 2 THEN
PAUSE 2
endif
IF DUR = 4 THEN
PAUSE 4
endif
IF DUR = 8 THEN
PAUSE 8
endif
PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0
PAUSE 1000
GOTO MAIN


the program is running the FLASH routine without actually sending a pulse out to the FETs unless one of the inputs is triggered. I know this because I can measure the time delay between applying an input signal and waiting for an output.

So my question is, why is there up to a 1 second delay between applying a signal and getting an output?

jmgelba
- 17th March 2009, 16:52
Nevermind - I see it. The flash routine will only fire the FETS if there is an input, it will still run the routine if there is an input or not. OK, so, how do I get it to go back to the start of the program if there is no input rather than go through the whole flash routine and wait that 1000mS?

Acetronics2
- 17th March 2009, 16:57
Got it !!!

I only can pass the program ( AT Tiny ...) but it can give you some ideas.
the article with scheme ( nothing special ) is 400 kb ..

But you can retrieve it from the english Elektor site. ( year is 2006 )

Alain

jmgelba
- 17th March 2009, 17:08
Thanks for the zip!

OK, getting there. Here is the code at the moment.


OSCCON = $70 'set internal resonator to 8mhz
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 5 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 20 ' Set sampling time in uS
DEFINE OSC 8
BNK1 VAR WORD
BNK2 VAR WORD
DUR VAR WORD


ADCON0 = %00000001
ADCON1 = %01111100
ADCON2 = %10111110

TRISA = %11111111
TRISB = %11110000

PORTB.0 = 1
PORTB.1 = 1
PORTB.2 = 1
PORTB.3 = 0

BNK1 = 0
BNK2 = 0
DUR = 0

MAIN:
DUR = 0
PORTB.3 = 0
BNK1 = 0
BNK2 = 0
ADCIN 0, BNK1
ADCIN 1, BNK2

IF PORTB.4 = 1 then
DUR = 8
endif
IF PORTB.5 = 1 THEN
DUR = 4
endif
IF PORTB.6 = 1 THEN
DUR = 2
endif
IF PORTB.7 = 1 THEN
DUR = 1
endif
IF (BNK1 => 466) OR (BNK2 => 466) THEN FLASH
goto MAIN




FLASH:
if PORTA.4 = 0 or PORTA.5 = 1 THEN
GOTO MAIN
ENDIF
IF PORTA.4 = 1 or PORTA.5 = 0 THEN
PORTB.0 = 0 : PORTB.1 = 0 : PORTB.3 = 1
endif


IF DUR = 1 THEN
PAUSE 1
endif
IF DUR = 2 THEN
PAUSE 2
endif
IF DUR = 4 THEN
PAUSE 4
endif
IF DUR = 8 THEN
PAUSE 8
endif
PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0
pause 1000
GOTO MAIN



The problem is with the inputs. It will not fire the outputs unless PORTA.4 = 1 AND PORTA.5 = 0

I need this to be OR just like it is in the code. Program works perfectly if I have both inputs connected, but I need to be able to fire if there is a 1 on A.4 or if there is a 0 on A.5

Thats my last issue.

Acetronics2
- 17th March 2009, 17:30
just try




FLASH:

IF (Porta.4 AND NOT Porta.5) THEN

PORTB.3 = 1
PAUSE DUR

PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0
pause 1000

ENDIF

GOTO MAIN

Bruce
- 17th March 2009, 18:15
I would replace PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0 with a single write to the whole
port to help reduce my chances of read-modify-write.

You can make your code a lot smaller/faster also by adjusting a few simple routines.

Below are just a few suggestions.


PORTB = %00000111 ' setting port latches "before" tris avoids pin glitches
TRISA = %11111111
TRISB = %11110000

'PORTB.0 = 1 ' done above
'PORTB.1 = 1 ' Note: this can cause read-modify-write problems
'PORTB.2 = 1
'PORTB.3 = 0

'BNK1 = 0 ' taken care of below
'BNK2 = 0
'DUR = 0

MAIN:
DUR = 0
' PORTB.3 = 0 ' taken care of at POR and end of Flash routine
BNK1 = 0
BNK2 = 0
ADCIN 0, BNK1
ADCIN 1, BNK2

' IF PORTB.4 = 1 then
' DUR = 8
' endif
' IF PORTB.5 = 1 THEN
' DUR = 4
' endif
' IF PORTB.6 = 1 THEN
' DUR = 2
' endif
' IF PORTB.7 = 1 THEN
' DUR = 1
' endif

' reverse how DIP switch assigns 8,4,2,1 with
' IF RB7 = 1 DUR = 8
' IF RB6 = 1 DUR = 4
' IF RB5 = 1 DUR = 2
' IF RB4 = 1 DUR = 1

' now just shift upper 4-bits read from DIP switch
' AND make sure upper 4-bits of result in DUR are clear.
DUR = (PORTB >> 4) & $0F
' returns 8, 4, 2 or 1 in DUR if "ONLY 1" of RB7, RB6, RB5 or RB4 are set.

IF (BNK1 => 466) OR (BNK2 => 466) THEN FLASH
goto MAIN

FLASH:
IF (PORTA.4=1) OR (PORTA.5=0) THEN
' PORTB.0 = 0 : PORTB.1 = 0 : PORTB.3 = 1
PORTB = %00001100 ' avoids read-modify-write
endif

' IF DUR = 1 THEN
' PAUSE 1
' endif
' IF DUR = 2 THEN
' PAUSE 2
' endif
' IF DUR = 4 THEN
' PAUSE 4
' endif
' IF DUR = 8 THEN
' PAUSE 8
' endif
PAUSE DUR ' DUR already holds the PAUSE time. This saves a lot of code.

' PORTB.0 = 1 : PORTB.1 = 1 : PORTB.3 = 0
PORTB = %00000111 ' avoids read-modify-write
GOTO MAIN

END
I don't know which PIC you're using, but I would also check to make sure RA4 and RA5 are
both set to digital "analog disabled" for these pins so they don't return the wrong value
when being tested.

jmgelba
- 17th March 2009, 20:04
Bruce, thanks for the awesome post. I feel edumacated now!

Actually before I saw your post I changed a few things and got the board working perfectly. I'll include your port setting changes to remoe the potential RMW errors. Thanks for that suggestion.

However, I am unable to implement the reversal of dip swith settings as the board is laid out and silkscreen shows 1, 2, 4 and 8mS.


So, has anyone ever seen 6 LED's pulling over 1.5KW?!

Acetronics2
- 18th March 2009, 08:28
Hi, JM



However, I am unable to implement the reversal of dip swith settings


May be you could have a look to manual $ 4.17.11

REV command ...

Alain