Pages: [1] 2   Go Down
Author Topic: Strange behavior on digital pins  (Read 1098 times)
0 Members and 1 Guest are viewing this topic.
Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I made little board for controlling rooms light with IR remote control, rotary encoder, and push buttons. One light source is LED, driven by FET using arduinos pwm, other one is incandescent - controlled by relay. Once in a couple of days something strange happens... When rotary encoder is left in A channel High state. irDATA pin goes ~1 volt higher and starts to fluctuate (like random noise) so triggering irDATA interrupt routine... Same thing was happening on genuine arduino uno board. There is some kind of crosstalk between pins 4 and 5 of Atmega controller... but most of the time its ok.

I've attached my pcb and circuit schematic.


* pcb.png (87.4 KB, 1021x735 - viewed 26 times.)

* schematic.png (120.65 KB, 1503x869 - viewed 46 times.)
« Last Edit: December 20, 2012, 09:33:21 am by Arty » Logged

Offline Offline
Edison Member
*
Karma: 5
Posts: 1730
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Probably because that input is floating, that makes it the most susceptible to noise, a pulldown or pullup resistor would fix that, easiest just use the internal pullup on the pin
Logged

Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well.. as you can see from schematic, I have external pullup or pulldown (regarding to polarity) resistor for every input, exept for irDATA line, where internal pullup is used (tried to add external 100k resistor, to lower the summary resistance of pullup (lower can probably fry the ir detector), but that made no difference...
Logged

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2916
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A couple of things,

- I'm not too surprised you may get some glitches, due is all sorts of external factors, when
  attempting to run an embedded controller continuously for long periods of time. Industrial
  systems tend to have all sorts of safeguards for such operation, eg, watchdog resets, ESD
  and EMI protection on external lines, extra filtering on the power supplies, more bypass
  caps than you show, on and on. It's not always trivial to build a reliable system, for a
  general environment.

- secondly, some of your caps seem to have the wrong values. You probably mean 100nF for
  C1, but C2,C3 should be 18-22 pF, not 100 pF for a 20 Mhz xtal.
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That schematic has several inappropriate capacitor values - the ones oric mentioned in the previous post and then some more. But if the behaviour occurs when using a real Arduino board as well, then the problem may well be in software. Writing embedded software that runs reliably for weeks on end on a microcontroller is not the same as hacking a program that runs for a few seconds or minutes on a PC. But you haven't posted your code, so I can only speculate about the source of the problem.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Offline Offline
Edison Member
*
Karma: 5
Posts: 1730
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What makes you say a value less than 100k would fry the sensor? 10k I imagine would be a better number to use, and unless it really cand handle much current you could go lower than 1k
Logged

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2916
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But if the behaviour occurs when using a real Arduino board as well,

Maybe, maybe not. His custom pcb is designed to nicely interface to his sensors,etc.
OTOH, connecting to a regular Arduino board instead, he'll have a lot of stray wires
hanging all over the place. Will be even worse in regards extraneous noise pickup,
&etc.
Logged

Valencia, Spain
Offline Offline
Faraday Member
**
Karma: 149
Posts: 5626
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It sounds more like a power supply problem to me. Mains voltage brownouts/spikes.

It could also be a decoupling problem. The 100nF capacitor on VCC is smaller than Atmel's reccomended 0.22 µF.

Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm sorry for mistakes in schematic... I've corrected them to represent the real world situation, it was only on the paper. Ok, I will try some bigger decoupling cap, and see how it goes. As for pullup on irDATA line from TSOP1840 IR detector - it already has 100k internal pull up, plus arduino 20k plus extra 100k makes around 14k summary resistance, so I doubt the problem is pullups. When the glitch happen, I checked power with osciloscoope and it was clean and steady, so PSU is not the issue either. The main problem is I can't replicate the thing... it just comes and goes without any external factor, what makes the debugging a real nightmare. Anyway, here is the code (Yes, I know its a bit mess, and will be hard to understand since my comments are mainly in Latvian)...

Code:

int ir_pin = 2; //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;    //"Ready to Receive" flag, not needed but nice
int debug = 0;    //Serial connection must be started to debug
int start_bit = 2000; //Start bit threshold (Microseconds)
int bin_1 = 1000;    //Binary 1 threshold (Microseconds)
int bin_0 = 400;      //Binary 0 threshold (Microseconds)
const int rly_pin = 8;
const int SPKR = 12;
const int sw_pin = 7;
const int ledsw_pin = 6;
int sw = 0;
int prevsw = 0;
int ledsw = 0;
int prevledsw = 0;
int fadeValue = 0;
volatile int fadetarget = 255;
volatile int offtrg = 0;
int pwm_pin = 5;
int fadestep = 25;          // solis pa kādu mainās gaisma LED+ un LED-
int fadeSpeed = 1;
int prevValue;
volatile int gaisma = 0;
int minimumFade = 1;       // minimaalais atljautais fade value
// variables encoderim --- //
const int pin_A = 3;  // pin 3
const int pin_B = 4;  // pin 11
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
int rfeedback;
// --- END --- //


void setup() {
 pinMode(ir_pin, INPUT);
 digitalWrite(ir_pin, HIGH);
 digitalWrite(led_pin, LOW); //not ready yet
 Serial.begin(115200);
 pinMode(SPKR, OUTPUT);
 pinMode(led_pin, OUTPUT);
 pinMode(rly_pin, OUTPUT);
 pinMode(sw_pin, INPUT);
 digitalWrite(rly_pin, LOW);
 attachInterrupt(0, getIR, LOW);    // interrupt 0
 pinMode(pwm_pin, OUTPUT);
 // --- Variables encoderim --- //
   pinMode(pin_A, INPUT);
   digitalWrite(pin_A, HIGH);
  pinMode(pin_B, INPUT);
  digitalWrite(pin_B, HIGH);
  attachInterrupt(1, encoder, CHANGE);
 // --- END --- //
 
}


void beep(int garums, int frekvence){
  for (int i=0; i < garums; i++) {  // gjenereejam vajadziigo beepu
  digitalWrite(SPKR, HIGH);
  delayMicroseconds(frekvence);
  digitalWrite(SPKR, LOW);
  delayMicroseconds(frekvence);
  }
}


void loop() {
if (led_pin == LOW || rfeedback <= 25) {
  rfeedback++;
}else{
  digitalWrite(led_pin, HIGH);
  rfeedback = 0;
}
delay(7);
sledzis();
ledswitch();
fader();
}


void fader() {
  if (fadetarget > fadeValue){ 
  fadeValue += fadeSpeed;
  analogWrite(pwm_pin, fadeValue);
  if (fadeValue == 255) beep(100, 250);
//  Serial.print("Feidojam LED uz: ");
Serial.println(fadeValue);
  }
  if (fadetarget < fadeValue){
   fadeValue -= fadeSpeed;
   analogWrite(pwm_pin, fadeValue);
   if (fadeValue == minimumFade) beep(100, 250);
//   Serial.print("Feidojam LED uz: ");
Serial.println(fadeValue);
  }
}

void sledzis(){
  sw = digitalRead(sw_pin);
  if (sw == 0 && prevsw == 1){
   beep(100, 250);
     if (gaisma == LOW){
       digitalWrite(rly_pin, HIGH);
       gaisma = HIGH;
     }else{
       digitalWrite(rly_pin, LOW);
       gaisma = LOW;
     }
     Serial.print("Gaismas statuss: ");
     Serial.println(gaisma);
     delay(200);
  }
  prevsw = sw;
}


void ledswitch(){
  ledsw = digitalRead(ledsw_pin);
  if (ledsw == 0 && prevledsw == 1){
     beep(100, 250);
   if (fadetarget == 0){
    fadetarget = prevValue;
    offtrg = 0;
    Serial.println("Iesleedzam LED gaismas!");
  }else{
    fadetarget = 0;
    offtrg = 1;
    prevValue = fadeValue;
     Serial.println("Izsleedzam LED gaismas!");
  }
delay(200);
}
  prevledsw = ledsw;
}


void getIR() {
detachInterrupt(0);
    static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
   // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 100)
  {
   int tempKey = getIRKey();
   Serial.print("No pults sanjeemaam: ");
    Serial.println(tempKey);
//   if (tempKey > 0) beep(100, 250);
 
  if(tempKey == 2320){ // ------------------- Gaismas on/off key
    if (gaisma == LOW){
       digitalWrite(rly_pin, HIGH);
       gaisma = HIGH;
     }else{
       digitalWrite(rly_pin, LOW);
       gaisma = LOW;
     }
     Serial.print("Gaismas statuss: ");
     Serial.println(gaisma);
  }

  if(tempKey == 16){ // -------------------- LED Off key
  if (fadetarget == 0){
    fadetarget = prevValue;
    offtrg = 0;
    Serial.println("Iesleedzam LED gaismas!");
  }else{
    fadetarget = 0;
    offtrg = 1;
    prevValue = fadeValue;
     Serial.println("Izsleedzam LED gaismas!");
  }}

  if(tempKey == 2064){ // ------------------ LED + key
  if (offtrg == 1){
      fadetarget = fadeValue;
      offtrg = 0;
   }
    fadetarget = constrain((fadetarget + fadestep), minimumFade, 255);
     Serial.print("LED gaismas liimenis: ");
     Serial.println(fadetarget);
   }
 
   if(tempKey == 1040){ // ---------------- LED - key
    if (offtrg == 1){
      fadetarget = fadeValue;
      offtrg = 0;
   }
  fadetarget = constrain((fadetarget - fadestep), minimumFade, 255);
     Serial.print("LED gaismas liimenis: ");
     Serial.println(fadetarget);
   }
  }
  last_interrupt_time = interrupt_time;
  attachInterrupt(0, getIR, LOW);    // interrupt 0
}


void encoder(){
    encoder_A = digitalRead(pin_A);
    encoder_B = digitalRead(pin_B);   
    if((!encoder_A) && (encoder_A_prev)){
      if(encoder_B) {                         // Clockwise
fadetarget = constrain((fadetarget + 10), minimumFade, 255);
      } else {                                  // Counterclockwise
fadetarget = constrain((fadetarget - 10), minimumFade, 255);
      }
    }
    if((encoder_A) && (!encoder_A_prev)){
      if(!encoder_B) {                        // Clockwise
fadetarget = constrain((fadetarget + 10), minimumFade, 255);
      } else {                                  // Counterclockwise
fadetarget = constrain((fadetarget - 10), minimumFade, 255);
      }
    }
    encoder_A_prev = encoder_A;     // Noglabaajam ieprieksheejo staavokli     
}


int getIRKey() {
 int data[12];
 data[0] = pulseIn(ir_pin, LOW); //Saakam meeriit bitus
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);
 digitalWrite(led_pin, LOW);

 if(debug == 1) {
   Serial.println("-----");
 }
 for(int i=0;i<=11;i++) {      //Parse them
   if (debug == 1) {
   Serial.println(data[i]);
   }
   if(data[i] > bin_1) {      //is it a 1?
data[i] = 1;
   }  else {
if(data[i] > bin_0) {      //is it a 0?
   data[i] = 0;
} else {
  data[i] = 2;    //Flag the data as invalid; I don't know what it is!
}
   }
 }
 for(int i=0;i<=11;i++) {      //Pre-check data for errors
   if(data[i] > 1) {
return -1;    //Return -1 on invalid data
   }
 }
 int result = 0;
 int seed = 1;
 for(int i=11;i>=0;i--) {     //Convert bits to integer
   if(data[i] == 1) {
result += seed;
   }
   seed = seed * 2;
 }
 return result;      //Return key number
}



* schematic.png (129.39 KB, 1574x903 - viewed 15 times.)
Logged

Offline Offline
Sr. Member
****
Karma: 9
Posts: 296
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you think R14 and R15 too high?

Quote
it just comes and goes without any external factor,
Is the whole contraption inside a grounded case/enclosure?
Logged

Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Not yet.. it is currently just the PCB laying on the desk, but when the glitch happen, I tried to wrap it in grounded foil - didn't help. I'm now trying to catch it happening again to make some video of the oscilloscope for you, to better understand the problem. I think R14 and R15 are ok, since almost no current is flowing to the gate of the FETs. Am I wrong? R11 and R16 are not needed at all, but I put them just for the protection of arduino if any of mosfets dies and shorts the gate pin.

BTW, I already tried to change the wire lengths to the switches, encoder, sensor board (shielded cable to this one).
« Last Edit: December 21, 2012, 07:16:34 am by Arty » Logged

Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I took a quick video of the device..
Logged

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2916
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As already noted, re long unshielded wires, lack of proper filters on I/O lines, on
and on, in regards hardly an industrial level glitch-reject design, your setup is really
just a big glitch waiting to happen. It's probably triggering on your neighbor's
microwave, whatever. See my first answer in post #3.
Logged

Riga, Latvia
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As already noted, re long unshielded wires, lack of proper filters on I/O lines,
Can you be more specific about this one?
on
and on, in regards hardly an industrial level glitch-reject design, your setup is really
just a big glitch waiting to happen. It's probably triggering on your neighbor's
microwave, whatever. See my first answer in post #3.
Thank god I don't have any neighbors closer than 0.5km smiley
Logged

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2916
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It's very difficult to say "here's all you need to do, blah, blah". In the industrial controller
world, I've seen companies spend months and many 10s of 1000s of $$$ trying top bullet
proof their designs. Adding all sorts of "fixes" on top of fixes, and their systems would
still glitch.

Re-read my first post again, as I mention a bunch of things. Firstly, your long unshielded
wires hanging out all over are just big antennas, especially if the lines have high-impedances.
For starters, you might look at this website,

http://ruggedcircuits.com/html/ruggeduino.html

Then lookup ESD, EMI, failsafe software practices, on and on. In "general", it's a big can of
worms, although if you're lucky, one or two things may help a large amount.


Logged

Pages: [1] 2   Go Up
Jump to: