Jump to content
Sign in to follow this  
iragdoll

Connecting Piezo Vibration Sensor to LaunchPad

Recommended Posts

Okay, so right now, it looks like there is some noise issues.

 

I have the vibration sensor connected just like this:

 

file.php?id=27

 

Except I have a 3.3v zener diode.

 

I have the transistor hooked up exactly like the schematic shown here: http://processors.wiki.ti.com/index.php ... _Drive_LED

 

I first tested out the transistor by it self, and it works. My main problem right now is when I put this code for the vibration sensor (Please check the code if I messed up anything)

#define __MSP430G2231__
#include 

#define PHOTOCELL BIT0 

int analogRead(unsigned int pin);

void main() {
 volatile unsigned int val;
 int threshold = 90;
 int delay;

 WDTCTL = WDTPW + WDTHOLD;
 P1DIR |= BIT6;
 //P1OUT = 0;

 ADC10CTL0 = ADC10ON + ADC10SHT_0 + SREF_0; // ACD10 on, 4 clock cycles per sample, Use Vcc/Vss references

 // change frequency to ~15.25mhz (DCO(15,3))
 BCSCTL1 |= (BIT0 + BIT1 + BIT2 + BIT3);
 DCOCTL &= ~(BIT7);
 DCOCTL |= (BIT6 + BIT5);

 for (; {
   val = analogRead(PHOTOCELL);
   if(val > threshold){
       P1OUT |= BIT6;
       delay = 0;
       while(delay < 1000)
               delay++;
       P1OUT &= ~BIT6;
   }
  }
 }

int analogRead(unsigned int pin) {
 ADC10CTL1 = ADC10SSEL_2 + pin;// Select MCLK and pin
 ADC10CTL0 |= ENC + ADC10SC; // enable and start conversion
 while (1) {
   if ((ADC10CTL1 ^ ADC10BUSY) & ((ADC10CTL0 & ADC10IFG)==ADC10IFG)) { // ensure conversion is complete
     ADC10CTL0 &= ~(ADC10IFG +ENC); // disable conversion and clear flag
     break;
   }
 }
 return ADC10MEM;
}

 

When i get close to any ground wires, the LED starts flickering. The main goal for this project is to be able to detect vibration while comparing the value to a set threshold. If it hits that threshold, the LED must stay on for a specified amount of time. If it does not hit the threshold, the LED should stay off.

 

The vibration sensor seems to be working because when I shake it, it blinks the LED. (Its hard to see because if you get close to a ground wire it starts blinking by itself)

 

Thanks!

Share this post


Link to post
Share on other sites

The vibration sensor seems to be working because when I shake it, it blinks the LED. (Its hard to see because if you get close to a ground wire it starts blinking by itself)

 

you may want to try and use a wooden stick to "poke" the sensor from 1 meter away to isolate the impact of your "body" capacitance. :D

 

anyway, i am not familiar to this type of device, but i do also have noise problem on various adc projects.

 

. you may want to sleep while u are taking adc measures, this will avoid interference from the mcu itself.

. will help if u go further and turn your io pins to input and floating.

. when u are consecutively reading adc in your while loop, avoid doing io, ie. don't turn on your led yet.

. moving your led to p2 may help (p1.0 is adc0)

. if u are running on a breadboard, be sure to add 100nF cap close to mcu between gnd and vcc.

. run your sampling slower i.e. change ADC10SHT_0 to 1 or 2.

. if your application allows, try to run slower, i.e 8Mhz, 4Mhz, etc.

 

in addition, the wait-for-adc-done condition check is over-engineered unnecessary (i had to use pen and paper to help myself understand it) and the single '&' would have failed if not ADC10BUSY happens to be bit0.

 

   if ((ADC10CTL1 ^ ADC10BUSY) & ((ADC10CTL0 & ADC10IFG)==ADC10IFG)) { // ensure conversion is complete

may be this way is more clear when someone want to adopt this code in the future

 

   if ((ADC10CTL1 & ADC10BUSY) && (ADC10CTL0 & ADC10IFG)) { // no good, corrected below

[EDIT]

sorry typo, the above should be

   if (!(ADC10CTL1 & ADC10BUSY) && (ADC10CTL0 & ADC10IFG)) {

we want to wait till adc is not busy and interrupt flag set..., sorry about that.

[/EDIT]

 

if u want to try sleeping, may want to try (i did not test it though)

 

int analogRead(unsigned int pin) {
 ADC10CTL1 = ADC10SSEL_2 + pin;// Select MCLK and pin
 ADC10CTL0 |= ENC + ADC10SC; // enable and start conversion
 __bis_SR_register(CPUOFF + GIE); // i rest so i can go further
 ADC10CTL0 &= ~(ADC10IFG +ENC); // disable conversion and clear flag, actually ADC10IFG is cleared automatically

 return ADC10MEM;
}

#pragma vector=ADC10_VECTOR
__interrupt void Adc10_Vector(void) {
   __bic_SR_register_on_exit(CPUOFF);  // Clear CPUOFF bit from 0(SR)
}

 

also be sure to ask for adc interrupt and enable interrupt in main()

 

 ADC10CTL0 = ADC10ON + ADC10SHT_0 + SREF_0 + ADC10IE; // may want also to try ADC10SHT_2, etc
   _BIS_SR(GIE);       // enable interrupt

 

also for the clock source, you are using sm clock w/ no division, i had only been using adc10 internal osc in my few projects (about 5mhz) w/ divide by 8, it may worth a try if u still got too much noise.

 

i.e.

ADC10CTL1 = ADC10SSEL_2 + pin;
.. change to
ADC10CTL1 = ADC10DIV_3 + pin;

 

hope this helps.

Share this post


Link to post
Share on other sites

Hey Guys,

 

I need some help again. I need to read the ADC on an interrupt basis so basically when the vibration sensor is hit, it should send an interrupt to run a function. Otherwise it should stay in LPM0. Any ideas?

 

Currently my code looks like this:

 

#define __MSP430G2231__
#include 

#define PHOTOCELL BIT0
#define LED BIT6

int analogRead(unsigned int pin);

void main() {
 volatile int val;
 int threshold = 45;

 WDTCTL = WDTPW + WDTHOLD;
 P1DIR |= LED;
 P1OUT = 0;

 ADC10CTL0 = ADC10ON + ADC10SHT_0 + SREF_0;

 for (; {
   val = analogRead(PHOTOCELL);

   if(val + 10 > threshold){
       P1OUT |= LED;
       __delay_cycles(1000000);
       P1OUT &= ~LED;
   }
  }
 }

int analogRead(unsigned int pin) {
 ADC10CTL1 = ADC10SSEL_2 + pin;
 ADC10CTL0 |= ENC + ADC10SC;

 while (1) {
   if ((ADC10CTL1 ^ ADC10BUSY) & ((ADC10CTL0 & ADC10IFG)==ADC10IFG)) { 
     ADC10CTL0 &= ~(ADC10IFG +ENC);
     break;
   }
 }
 return ADC10MEM;
}

Share this post


Link to post
Share on other sites
I need to read the ADC on an interrupt basis so basically when the vibration sensor is hit, it should send an interrupt to run a function. Otherwise it should stay in LPM0. Any ideas?

 

i think u need a different approach. adc won't generate an interrupt to wake u up. interrupt usage in adc is for waking u up after it finishes the adc conversion, i.e. u need to start an adc conversion in the 1st place. if u want to save power for non-activity, u can only sleep and have the timer wake u up periodically, or have a "digital" input to wake u up.

 

u may want to consider these two approaches.

 

(1) setup a timer to wake u up every 1/8 (1/32, or whatever suits) second, take an adc sample and see if u have any readings from the piezo. if no reading, u back to sleep and wait for 1/8 sec again. this will save u from reading adc all the time and save power. u can go to LMP2/3 for further power saving in this approach.

 

(2) elevate you piezo input to a digital logic hi level (2.7v+), connects it to a input pin, setup edge trigger interrupt on the pin and let it wakes u up. u get to go to LPM4 for even more power saving in this approach. cons, this will require additional components.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...