PDA

View Full Version : Oscillator stops when touching with a wire



Wilbert Ingels
- 23rd April 2008, 21:23
Good evening all,

I've made a RS485 network of 16 remote devices (16F886) and 1 master (18F2620) all running Picbasic pro. Everything runs perfectly, however, when i touch the ground or one of the inputs with a non connected wire (to connect an input with the ground for example), the clock stops running (wire is only connected on one side).

I've tried to change the capacitors of the xtal (changed it between 15pf and 22pf) but the result remains the same.

PIC's are configured in HS mode.

Any ideas how to solve this?

Many thanks !!

Wilbert

skimask
- 23rd April 2008, 21:39
Good evening all,
I've made a RS485 network of 16 remote devices (16F886) and 1 master (18F2620) all running Picbasic pro. Everything runs perfectly, however, when i touch the ground or one of the inputs with a non connected wire (to connect an input with the ground for example), the clock stops running (wire is only connected on one side).
I've tried to change the capacitors of the xtal (changed it between 15pf and 22pf) but the result remains the same.
PIC's are configured in HS mode.
Any ideas how to solve this?
Many thanks !!
Wilbert

How about decent cap's across Vdd and Vss?
Do you have a pull up on MCLR?

mister_e
- 23rd April 2008, 21:58
AND
1.make sure LVP is set to OFF on both
2.make sure ALL Vss & Vdd are connected.

If both run @5V, it shouldn't be a Brown-Out reset or... sort of.

Wilbert Ingels
- 24th April 2008, 11:05
Thanks for the replies !

Just to come back on the below feedback:
- Caps are used to stabilize power supply (100nf and 10mf) and also every PIC has a 100nf cap on the power supply pin
- MCLR has a pull-up resistor
- LVP set to off

Other ideas what it could be?

I can post the network drawing (Eagle file) but i'm not sure if i can attach files ...

Many thanks for helping me with this !!

Wilbert

Wilbert Ingels
- 24th April 2008, 11:15
Also the 2 VSS pins are connected ...

mackrackit
- 24th April 2008, 11:24
How good / stable is you power supply?

Wilbert Ingels
- 24th April 2008, 11:25
Some additional information:
- The processor doesn't reset but stops in my opinion. I've used debug information on a serial port. On each startup, an appropriate message is sent (which i don't receive when this problem occurs). I'm also displaying variables and when the processor continues, he still has the right values.
- Most of the cases, information on the RS485 network triggers the processor to continue.

Wilbert Ingels
- 24th April 2008, 11:29
Dave,

Good point, it's a lab power supply so i didn't had any doubt about it ... I'm going to check it now !

Thanks !

Wilbert

mackrackit
- 24th April 2008, 11:32
And how is the brown out fuse set?

Wilbert Ingels
- 24th April 2008, 12:17
Checked Power supply -> OK
Added additional caps -> problem remains
Changed Power supply -> problem remains
Changed cables -> problem remains

Even when i touch VDD with a none connected cable (15 cm), i see the clock stopping on multiple processors ...

Wilbert Ingels
- 24th April 2008, 12:26
Configuration bits:
device pic16F886, hs_osc, wdt_on, mclr_on, lvp_off, protect_off, cpd_on

Jerson
- 24th April 2008, 13:16
Hello Wilbert

I wonder if you have a firmware issue here. Have you handled the case when the data stream is corrupted? Perhaps your firmware is hanging on data corruption. The symptoms you describe could be due to this.

Jerson

Wilbert Ingels
- 24th April 2008, 14:21
Hello Jerson,

My first impression was also having a firmware issue. So i made a modification of the firmware so the only thing the controller is doing is listening to the RS485 bus and every 250ms reading PORTC of the controller when i put the controller in initialization mode through the RS485 bus. Every time he checks PORTC, a led flashes. This works perfectly, he read and understand commands from the RS485 bus, the led flashes but when i touch the ground with a non connected wire, the led stop flashing. When i connect a fixed wire to the ground, every thing works fine and the clock doesn't stop touching inputs ...

So now i made a second modification, only a flashing led, and guess what, the clock doesn't stop what makes me think again something is wrong in my code ...


This is my code:
'************************************************* ***************
'* Name : Module_O *
'* Author : Wilbert Ingels *
'* Notice : Copyright (c) 2008 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 19/11/2007 *
'* Version : 1.0 *
'* Notes : New Hardware 16F886 *
'* : *
'************************************************* ***************

'include "modedefs.bas"
DEFINE OSC 20
'define I2C_SLOW 1
'TRISC = %11111111 'PORTC is an input
TRISB = %11111111
TRISA = %11111111
CCP1CON = 0 ' DISABLE CAPTURE COMPARE MODULE
ADCON1 = 15
'CMCON = 7
ANSEL=0
ANSELH=0

'OSCCON = %01110111

data @0,"3","8","4","I","E" ' Device address

define DEBUG_REG PORTA
define DEBUG_BIT 1
define DEBUG_BAUD 115200
define DEBUG_MODE 0

define DEBUGIN_REG PORTA
define DEBUGIN_BIT 1
define DEBUGIN_MODE 0



'---------------------------------------------
'Variables and constants
'---------------------------------------------

TxD var PORTA.3 ' Transmit pin RS232
RxD var PORTA.2 ' Receive pin RS232
command var byte ' Storage for command
i var byte ' Storage for loop counter
temp var word ' Storage for temperature
DQ var PORTC.0 ' Alias DS1820 data pin
DQ_DIR var TRISC.0 ' Alias DS1820 data direction pin
RS485_mode var PORTA.0 ' Mode for RS485 chip (send or receive)
RS485_SR var PORTA.1 ' RS485 send/receive pin
led_blue var PORTA.5
onewire var PORTB.4
RS9600 con 84
RS19200 con 16416
Buffer_size2 con 6 'Number of bytes received from RS485 bus
RS485string var byte(buffer_size2)
Module_ID var Byte(4)
x var byte
y var byte
z var byte
u var byte
v var byte
s1 var byte
s2 var byte
w1 var word
mode var byte 'L->Live Mode,I->Initialization mode
mode_ID var byte 'N->New module,E->Existing module
sda var PORTB.0 ' I2C bus
rcl var PORTB.1



'---------------------------------------------
'Initialization
'---------------------------------------------
mode = "L" 'mode="L" -> live mode, mode="I" -> initialization mode
input Rxd 'RxD RS232 is an input
low RS485_mode 'RS485 receive mode
low PORTA.4 'Second pin of the blue led

read 4,mode_id 'Mode_ID
read 3,x
read 2,y
read 1,z
read 0,u

if mode_id<>"E" then 'ID is new and must be generated
gosub test_module_type
mode_id="N"
for i=0 to 2
random w1 'generate random ID
if w1.byte0<>255 and w1.byte0<>0 then 'Random value if ok
module_id[i]=w1.byte0
else 'Random value is not ok
Module_id[i]=171 'Random value (My bithday :))
endif
next i
serout2 TxD,RS19200,[13,10,"New Module ID: ",dec module_id[0]," ",dec module_id[1]," ",dec module_id[2]," ",module_id[3]," ",mode_id,13,10]
else 'It's an existing ID
Module_ID[3] = x 'copy ID from Eeprom into RAM
Module_ID[2] = y
Module_ID[1] = z
Module_ID[0] = u
endif

serout2 TxD,RS19200,[13,10,"Startup ",Module_id[3],y,z,u,13,10]

'---------------------------------------------
'Start Main Routine
'---------------------------------------------

loop:
if mode="L" then 'bus is in Live mode
gosub rs485_receive
endif
if mode="I" then 'bus is in Initialization mode
gosub rs485_receive_init 'check if broadcast messages are received
gosub check_inputs 'during initialization, inputs needs to be checked
endif
goto loop

'-----------------------------------------------
'Subroutines
'-----------------------------------------------

'-----------------------------------------------
' Test which type of module it is
'-----------------------------------------------

test_module_type:
input PORTB.0
input PORTB.1
TRISC = %11111111 'PORTC is an input
if PORTC=255 then 'intput module
'serout2 TxD,RS19200,[13,10,"I'm an input module ",13,10]
Module_ID[3] = "I"
else 'output module
if PORTB.0=1 and PORTB.1=1 then 'then i'm an output module
'serout2 TxD,RS19200,[13,10,"I'm an output module ",13,10]
TRISC = %00000000 'PORTC is an output
PORTC=0
i2cwrite sda,rcl,%01000000,0,[0],module_error
'serout2 TxD,RS19200,[" and I've Dimmer functionality ",13,10]
Module_ID[3] = "D"
goto end_module

module_error:
'serout2 TxD,RS19200,[" and I've Relais functionality ",13,10]
Module_ID[3] = "O"
end_module:
else
'serout2 TxD,RS19200,[13,10,"Undefined module (B0 and B1 <>1, C<>255) ",13,10]
x=255 'module is invalid
endif
endif
return



'-----------------------
' RS485
'-----------------------

rs485_receive: 'receive routine when in Live mode
low RS485_mode 'receive mode
debugin [WAIT("ST"),rs485string[5],rs485string[4],rs485string[3],rs485string[2],rs485string[1],RS485string[0]] 'wait untill a message comes in starting with "ST"
'serout2 TxD,RS19200,[DEC rs485string[5]," ",dec rs485string[4]," ",dec rs485string[3]," ",dec rs485string[2]," ",dec rs485string[1],13,10]
if rs485string[5]=Module_id[3] and rs485string[4]=Module_id[2] and rs485string[3]=Module_id[1] and rs485string[2]=Module_id[0] then 'message is for this module
if Module_id[3]="I" then 'input module
if RS485string[1]="I" then 'instruction read inputs is received
high led_blue
y=PORTC
pause 4
s1=y
s2=0
gosub rs485_send
low led_blue
endif
endif
if module_id[3]="D" or module_id[3]="O" then 'output module
PORTC = rs485string[1]
high led_blue
pause 4
s1="K"
s2=0
gosub rs485_send
low led_blue
endif
endif

if rs485string[5]=0 and rs485string[4]=0 and rs485string[3]=0 and rs485string[2]=0 then 'broadcast message is received
'serout2 TxD,RS19200,["Data received L ",RS485string[0],RS485string[1],13,10]
Gosub check_init
endif

low RS485_mode 'receive mode
return

rs485_send:
high RS485_mode 'send mode
debug Module_ID[3],Module_ID[2],Module_ID[1],Module_ID[0],s1,s2
low RS485_mode 'receive mode
return

rs485_receive_init: 'recive routine when in initialization mode
low RS485_mode 'receive mode
debugin 250,rs485_cont,[WAIT("ST"),rs485string[5],rs485string[4],rs485string[3],rs485string[2],rs485string[1],RS485string[0]] 'wait untill a message comes in starting with "ST"
'serout2 TxD,RS19200,["Data received I ",RS485string[0],RS485string[1],13,10]
if rs485string[5]=0 and rs485string[4]=0 and rs485string[3]=0 and rs485string[2]=0 then 'broadcast message is received
'serout2 TxD,RS19200,["Broadcast received ",RS485string[0],RS485string[1],13,10]
gosub check_init
endif
goto init_end
rs485_cont:
'here code when timeout
init_end:
return

check_init:
if rs485string[1]="I" and rs485string[0]="I" then 'initialization mode activated
mode="I" 'main routine will do a different loop
high led_blue
serout2 TxD,RS19200,[13,10,"Init mode ",mode,13,10]
endif

if rs485string[1]="L" and rs485string[0]="L" then 'live mode activated
mode="L" 'main routine will do a different loop
low led_blue
serout2 TxD,RS19200,[13,10,"Live mode ",mode,13,10]
endif
return

check_inputs: 'during initialization, inputs needs to be checked
if module_id[3]="I" then 'Module is an input Module
'TRISC = %11111111 'PORTC is an input
low led_blue
serout2 TxD,RS19200,["Check inputs ",mode,13,10]
x=PORTC
if x<>255 then 'Input button is pressed
s1=x
s2=mode_id 'E->existing,N->New
gosub rs485_send
serout2 TxD,RS19200,["RS485send ",13,10]
endif
endif
if module_id[3]="D" or module_id[3]="O" then 'Output module (Dimmer or digital Output)
x=PORTB.2
if x=0 then 'initialization button is pressed
s1=0
s2=mode_id 'E->existing,N->New
gosub rs485_send
endif
endif
high led_blue
return


end

Wilbert Ingels
- 24th April 2008, 16:04
Dave,

You're right, it is a firmware problem. The clock is not stopping but following is happening:

This is the instruction causing problems:
debugin 50,rs485_cont,[WAIT("ST"),rs485string[5],rs485string[4],rs485string[3],rs485string[2],rs485string[1],RS485string[0]]

When a not connected wire is touched to one of the connection, a small spike is generated on the RS485 bus. This what i think that happens than: The Debugin receives 1 bit and is endless waiting for the other bits to come. I've the impression that the timeout only works if a full byte is received.

Is my statement correct? How can this be resolved?

Many thanks !

Jerson
- 24th April 2008, 17:04
Wilbert

Good snooping. The glitch is causing your firmware NOT to see the ST sequence. So, you go on waiting till you catch it .... and guess what -- it doesnt come again!

A better technique would be to
1. Wait for byte1=S
2. Wait for byte2=T
3. Process packet

I hope you can fix this yourself.

Jerson

falingtrea
- 24th April 2008, 17:58
in the 485_receive part of your code you have a debugin without a wait value. I would put timeouts in all your serial communication calls just to be safe.

Another thing you can do is output some debug messages to the serial port showing where the program is. Once it locks up you can look at the last message and see where the code was when it died.

Wilbert Ingels
- 24th April 2008, 18:17
Hi Tim and Jerson,

I'm working in 2 modes: Live mode and initialization mode. In live mode, the processor will wait endless untill he receives "ST" with instructions from the bus master. In initialization mode, he will look at his inputs and also looks if broadcast information is received on his RS485 bus.

I've tried your suggestions but he's still going into a endless loop when a spike arrived on the bus. It looks like when one bit arrives, the timeout value doesn't count untill a full byte is arrived. He only succeed to release (via timeout) when information flows again on the RS485 bus (and bytes are being received).

It seems that timeout only works when full bytes arrives. If a single bit (spike) arrives on the RS485 network, the debugin timeout statement is not working ...

Does serin2 works different than Debugin (-> timeout bit versus byte)?

Any other suggestions?

Many thanks guys !!

Wilbert

skimask
- 24th April 2008, 18:25
Why not "SERIN" all of your characters into a 'sliding buffer string' and keep that in a tight loop. You can keep track of it and keep checking if the beginning of that 'sliding buffer string' contains the "ST" that you're looking for. When it does, you save the data and act on it accordingly.
That way, you should be able to avoid the timeout and glitch problems that you're having.
I thought I had a good idea for you...lost it...can't find it again :)

Wilbert Ingels
- 24th April 2008, 18:57
Hey Skimask,

Thanks for your reply !

I'm still struggling how to do it. If i use a tight loop with timeout which receives character by character, i'm afraid if only one bit is send (my famous glitch :)), the timeout statement won't work and the endless loop will start (untill additional information is received)

I'm going to try it and will keep you in touch. If you remember you other suggestion, you're more than welcome :)

Take care

Wilbert

Wilbert Ingels
- 24th April 2008, 19:14
If i look in the manuel on page 135 (serin2) "if the serial input pin stays in the idle state during the timeout time, the program will exit the SERIN2 command and jump to label". In my case, the input pin doesn't stay idle because it received one glitch ...

Same for Debugin on page 58 ...

Hum, i don't see it yet how i can solve it

mister_e
- 24th April 2008, 19:40
Pull-up or pull-down resistor is an easy to test Solution?

Ron Marcus
- 24th April 2008, 19:56
It sounds like static electricity is the culprit here. I understand touching an input, but the ground should be somewhat immune to the phenomena. It sounds like there is a ground loop in the connections. Look for multiple lines connected to ground in the same run of cable. Touching one will cause an imbalance. So if the shield is connected to ground, and another line in the cable is, this could cause a problem. The simplest fix is to not connect the shield on one end of the cable. While it sounds counter intuitive, it might be the cause, or one of them.
Ron

skimask
- 24th April 2008, 22:41
If i look in the manuel on page 135 (serin2) "if the serial input pin stays in the idle state during the timeout time, the program will exit the SERIN2 command and jump to label". In my case, the input pin doesn't stay idle because it received one glitch ...

The fix might be something as simple as:


loop:
datagood = 0
SERIN2 (((your code here with the shortest timeout possible, timeoutlabel, etc.etc....)))
datagood = 1
goto overtimeoutlabel
timeoutlabel: if datagood = 0 then goto loop 'data was bad, try again
overtimeoutlabel: continue code here....

if it does glitch, you check 'datagood'. If datagood is 0, then it glitched or didn't receive what you wanted and try again

Aside from that, I agree with the other guys, ya gotta find the root cause of the glitches...

Wilbert Ingels
- 25th April 2008, 08:51
Hey Guys,

Thanks for the feedback !

Yesterday, i've changed the RS485 chips. I was using SN75176 and i've changed them for MAX481 and the glitched are gone. It seems that SN75176 is more sensible and thus in my case less usable in my application. The MAX481 untill now never gave one glitch. I'm working now on the timing aspects because these seems different between SN75176 and MAX481.

I've also went into more detail in how PBP works. I understand the little drawbacks (in terms of serial communication) of the language better now but i must say that, the longer i work with PBP, the more enthusiastic i am. It is a great language and a fantastic tool.

Take care

Wilbert