Electronics > Beginners

Trivial circuit upset by touching it

(1/2) > >>

beatle:
Hello!

I had an erratic circuit on my hands the day before, most likely to some dumb beginner's mistake, but I cant figure it out. Before you ask I don't have an oscilloscope to test it with (I am currently shopping for one).

I made a simple quick timer for a friend, that is supposed to beep regularly after 15 s or 30 s or 1 min intervals selected by a button press (for exercising). For that purpose I have:
a msp430g2432 uC,
a 10k pullup to !RST,
a pjezo buzzer connected to P1.4 and P1.5,
a button to P1.3,
a external watch crystal

I am using a breadboard.

The current code I am using:

--- Code: ---#include <msp430.h>
#include <sys/types.h>

#define     BUZZ1                   BIT5
#define     BUZZ2                   BIT4
#define     BUZZ_DIR               P1DIR
#define     BUZZ_OUT               P1OUT

#define     BTN_DIR         P1DIR
#define     BTN_IN          P1IN
#define     BTN_OUT         P1OUT
#define     BTN_REN         P1REN
#define     BTN             BIT3

#define     BEEP_LENGHT     200
#define     BEEP_FREQ       200
#define     BEEP_PAUSE      8000

#define     TIMER_15S      1024     // 2s currently for testing

void initialize(void);
static void __inline__ delay(register uint16_t n);
void beep(int);
void start_timer(void);
void stop_timer(void);

int mode = 0;

int main(void)
{
    delay(1);
    initialize();
    delay(1);

    while (1) {
    }
}

void initialize(void)
{
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT

    BUZZ_OUT &= ~(BUZZ1 + BUZZ2);  //  off
    BUZZ_DIR |= BUZZ1 + BUZZ2;     // Set as output

    BTN_DIR &= ~BTN;  // Set input
    BTN_REN |=  BTN;  // Enable pulldown
    P1IES &= ~BTN;   // low -> High is selected with IES.x = 0.
    BTN_OUT &= ~BTN;  // Set pulldown
    P1IFG &= ~BTN;  // To prevent an immediate interrupt, clear the flag for  P1.3 before enabling the interrupt.
    P1IE |= BTN;    // Enable interrupts for P1.3

    BCSCTL3 |= XCAP_3; //12.5pF cap- setting for 32768Hz crystal
    delay(50000);   // let crystal stabilize
    BCSCTL1 |= DIVA_3; // ACLK/8

    _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt
}

static void __inline__ delay(register uint16_t n)
{
    __asm__ __volatile__ (
            "1: \n"
            " dec %[n] \n"
            " jne 1b \n"
            : [n] "+r"(n)
            );
}


void start_timer(void)
{
    TACCR0 = 0; // Stop timer
    TACTL = MC_0; // Halt timer

    switch (mode) {
        case 1:
            TACCR0 = TIMER_15S; // 512 -> 1 sec, 30720 -> 1 min
            break;
        case 2:
            TACCR0 = TIMER_15S * 2;
            break;
        case 3:
            TACCR0 = TIMER_15S * 4;
            break;
        default :
            beep(4);
            return;
            break;
    }

    TACTL = TASSEL_1 + ID_3 + MC_1 + TACLR; // ACLK, /8, upmode, clear timer
TACCTL0 = CCIE;         // Enable interrupts for CCR0.
}

void stop_timer(void)
{
    TACCR0 = 0; // Stop counting
    TACTL = MC_0; // Halt timer
TACCTL0 &= ~CCIE;         // Disable interrupts for CCR0.
}

void beep(int times)
{
    int i;

    BUZZ_OUT |= BUZZ1;
    while (times>0) {
        times--;
        i = 0;
        while (i<BEEP_LENGHT) {
            i++;
            BUZZ_OUT ^= BUZZ1 + BUZZ2;
            delay(BEEP_FREQ);
        }
        delay(BEEP_PAUSE);
    }
    BUZZ_OUT &= ~(BUZZ1 + BUZZ2);  //  off
}

    __attribute__((interrupt(TIMERA0_VECTOR)))
void Timer_A (void)
{
    beep(mode);
}

__attribute__((interrupt(PORT1_VECTOR)))
void Btn_press(void)
{
    stop_timer();
    switch(P1IFG&BIT3) {
        case BIT3:
            P1IFG &= ~BIT3;    // clear the interrupt flag
            mode++;
            if (mode>3) {
                mode = 0;
                break;
            }
            beep(mode);
            if (mode != 0) {
                start_timer();
            }
            break;
        default:
            P1IFG = 0;    // probably unnecessary, but if another flag occurs
            // in P1, this will clear it.  No error handling is
            // provided this way, though.
            break;
    }
    delay(65000);
    P1IFG &= ~BIT3;    // clear the interrupt flag
}

--- End code ---

I am powering it with a 3.3V from mains power supply that I made for another project, but latter I want to use a 3V button cell.

The circuit and code works more or less as it should, but ONLY when I am touching one of the power rails with my finger! If not, the uC just freezes and does no beeping.

My main hypotheses as of why it is happening, was that the power supply is too noisy and I acted as a smoothing capacitor, but I tried adding capacitors of various values to no effect and I have powered other uC projects from the same supply before.

Now I am only guessing.. to little noise to start the quartz crystal oscillating (I am suspicious that it doesn't work that way) that my body is inducing in the circuit as a antenna? - tried adding a long wire to power rail and wrapping it around noisy lamp. No.

Wrong loading capacitances for external watch crystal (I am using soft controlled 11pF ones from the MSP430,  I have no idea what is the required values for my crystal) - tried changing it whit some 2.2pF parts in series. Nope (? I guess it should at least function, if with wrong frequency, and see no reason for it to work perfectly when I am touching the ) or 3.3V wire).

I suspect that the problem is connected to the fact that I am using deep sleep mode in my uC and waking up only to service timer interrupts (that is driven by the external crystal) and maybe something is incorrectly configured, but I have no clue how me touching the circuit can affect it in any way..

So, if someone can point me to a possible cause for this, please let me know!
(And sorry about the long write-up. I am not a native speaker and therefore very clumsy with English.)

Psi:
Sounds more like you have a grounding issue.
Your body will pull a floating circuit closer to mains earth

T4P:
Floating ground somewhere . ( Rather , disconnected ground )

steaky1212:
does it work when powered from the watch battery?

start simple, and have the uc just run a flashing LED in a for loop. That way you ensure the uc is running without having to worry about isr's.
Does the circuit work when connected to your PC for programming/debugging?

Connect the circuit ground to your PC ground - resolving the grounding issue.

beatle:

--- Quote from: Psi on May 01, 2012, 09:23:31 am ---Sounds more like you have a grounding issue.
Your body will pull a floating circuit closer to mains earth


--- End quote ---
I hadn't considered that. I am quite the beginner so forgive me if I am being silly, but if my power supply uses an isolating transformer does it still mean that my circuit ground should be close to mains earth?


--- Quote from: Dave.S on May 01, 2012, 09:42:55 am ---Floating ground somewhere . ( Rather , disconnected ground )

--- End quote ---
If there is an open circuit somewhere, how can me touching one of the supply rails upstream from the fault fix it?


--- Quote from: steaky1212 on May 01, 2012, 10:20:47 am ---does it work when powered from the watch battery?

start simple, and have the uc just run a flashing LED in a for loop. That way you ensure the uc is running without having to worry about isr's.
Does the circuit work when connected to your PC for programming/debugging?

Connect the circuit ground to your PC ground - resolving the grounding issue.

--- End quote ---

You are right, I should have used a reductionist approach for this.
Haven't tested with the battery yet, will buy one and check it out. And I have been doing it in a very bad way - programming chip in the Lounchpad socket and moving it to the breadboard every time. Attaching the Lounchpad to the circuit will give me multiple benefits.

You guys are very helpful, I will try these things out when I get home and report back. Thank you for your input, I was quite stuck!

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod