Jump to content
43oh

NatureTM

Members
  • Content Count

    218
  • Joined

  • Last visited

  • Days Won

    13

Posts posted by NatureTM

  1. I did a lot of work on battery-operated parking sensors for a startup recently.  We used magnetic sensors that are sensitive enough to detect distortions in the earth's magnetic field.  The iron an an automobile distorts the field and either increases or decreases the detected field which is read from the sensor by ADC.  They're quite low power to begin with, plus you can switch them on with a transistor for low duty-cycle sampling, leading to very long operation from battery.

     

    http://www.magneticsensors.com/vehicle-detection-solutions.php

     

    In our project we used the HMC1021 in our case.  I don't think I'm able to share code, but they were very simple to operate, and the datasheet has nice example circuits.

  2. Hi everyone, it's been awhile.

     

    I just wanted to share something interesting lasershark mentioned on my blog awhile ago.  It's basically a way to make music with one line of code.  It took about 15 minutes to implement on a g2553 and only requires a launchpad and a speaker.  I found it pretty entertaining.  Just connect one terminal of the speaker to Port 1.2 and the other to ground, or drive it with a transistor.

     

    Original project @ http://canonical.org/~kragen/bytebeat/

     

    #include "msp430g2553.h"
    
    #define MCLK						8000000
    #define OUTPUT_SAMPLES_PER_SECOND	                8000
    
    #define PIN_SPEAKER					BIT2
    
    unsigned long t = 0;
    
    unsigned char sample;
    
    void main(void) {
    	WDTCTL = WDTPW + WDTHOLD;
    	
    	DCOCTL = CALDCO_8MHZ;
    	BCSCTL1 = CALBC1_8MHZ;
    
    	P1SEL |= PIN_SPEAKER;
    	P1DIR |= PIN_SPEAKER;
    
    	TA0CTL = TASSEL_2 | MC_1;
    	TA0CCR0 = (0x0001 << 8) - 1;
    	TA0CCTL1 |= OUTMOD_7;
    
    	TA1CTL = TASSEL_2 | MC_1;
    	TA1CCR0 = MCLK / OUTPUT_SAMPLES_PER_SECOND - 1;
    	TA1CCTL0 |= CCIE;
    
    	_enable_interrupts();
    
    	while(1){
    		sample = ((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7;
    //		sample = t*(((t>>12)|(t>>8))&(63&(t>>4)));
    //		sample = (t*(t>>5|t>>8))>>(t>>16);
    //		sample = t*(((t>>9)|(t>>13))&(25&(t>>6)));
    //		sample = t*(((t>>11)&(t>>8))&(123&(t>>3)));
    
    //		sample = (t*5&t>>7)|(t*3&t>>10);
    //		sample = (t&t%255)-(t*3&t>>13&t>>6);
    //		sample = t>>4|t&((t>>5)/(t>>7-(t>>15)&-t>>7-(t>>15)));
    //		sample = (t*9&t>>4|t*5&t>>7|t*3&t/1024)-1;
    //		sample = ((t*(t>>12)&(201*t/100)&(199*t/100))&(t*(t>>14)&(t*301/100)&(t*399/100)))+((t*(t>>16)&(t*202/100)&(t*198/100))-(t*(t>>17)&(t*302/100)&(t*298/100)));
    //		sample = t*(t^t+(t>>15|1)^(t-1280^t)>>10);
    //		sample = t&t>>8;
    
    		//44 khz
    //		sample = ((t/2*(15&(0x234568a0>>(t>>8&28))))|t/2>>(t>>11)^t>>12)+(t/16&t&24);
    //		sample = ((t*("36364689"[t>>13&7]&15))/12&128)+(((((t>>12)^(t>>12)-2)%11*t)/4|t>>13)&127);
    
    		t++;
    		LPM0;
    	}
    }
    
    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void T1A0_ISR(void)
    {
    	TA0CCR1 = sample;
    	LPM0_EXIT;
    }
    

     

    Switch which "sample =" line is uncommented to change the "song."  The songs are from http://pelulamu.net/countercomplex/music_formula_collection.txt and there are more in that file.

     

     

  3. Here's something I had going awhile back. I didn't finish it do to some bug/got bored/meh. The circuits are the same as what gordon posted. My intent was to send the distance data to another uC through serial. Here's the code I had going and a pic. Hopefully I left things in a working state.

     

    PS Don't look at the code if you wanted to figure it out yourself. I think I was pretty close to finished.

     

    #include "msp430g2231.h"
    //#include 
    
    #define PIN_RECEIVER				BIT4
    #define PIN_TRANSMITTER				BIT2
    // SPI pins for reference, do not affect code: 
    #define PIN_SCLK					BIT5
    #define PIN_SDO						BIT6
    
    #define ADC_MAX						1023
    #define MCLK_FREQUENCY				16000000
    #define TRANSMITTER_FREQ			24000
    #define WDT_DIVIDER					64
    #define SPEED_OF_SOUND_IN_PER_SEC 	13071.3f
    #define MINIMUM_DISTANCE_IN			8
    #define MAXIMUM_DISTANCE_IN			600
    #define PINGS_AVERAGED 				1
    
    #define sendPing()					TACTL |= MC_1
    #define stopTransducer()			TACTL &= ~MC_1
    
    const unsigned long WDT_FREQUENCY = MCLK_FREQUENCY / WDT_DIVIDER;
    const float WDT_TICKS_PER_IN = (MCLK_FREQUENCY / WDT_DIVIDER) / SPEED_OF_SOUND_IN_PER_SEC;
    
    char iTransducerCycle = 0;
    char nTransducerCycles = 7;
    volatile unsigned long wdtCounter = 0;
    volatile unsigned long tPing;
    
    void setup(){
    const unsigned int SONAR_PERIOD = MCLK_FREQUENCY / TRANSMITTER_FREQ;
    
    DCOCTL = CALDCO_16MHZ;
    BCSCTL1 = CALBC1_16MHZ;
    
    WDTCTL = WDTPW + WDTTMSEL + WDTIS1 + WDTIS0;
    IE1 |= WDTIE;
    
    // setup pwm for ultrasound gen
    TACCTL1 |= OUTMOD_7;
    TACCR0 = SONAR_PERIOD;
    TACCR1 = SONAR_PERIOD / 2;
    TACCTL0 |= CCIE;
    TACTL |= TASSEL_2;
    P1DIR |= PIN_TRANSMITTER;
    P1SEL |= PIN_TRANSMITTER;
    
    // setup adc to capture echo
    ADC10CTL1 |= ADC10SSEL_3 + INCH_4;
    ADC10CTL0 |= ADC10ON + ENC + ADC10SHT_0;
    
    // setup USI
    USICTL0 |= USIPE6 + USIPE5 + USIMST + USIOE; // Port, SPI master
    //  	USICTL1 |= USIIE;                     // Counter interrupt, flag remains set
     	USICKCTL = USIDIV_7 + USISSEL_2;      // SMCLK/128 for 125000 baud @ SMCLK 16MHz
    	USICTL0 &= ~USISWRST;                 // USI released for operation
    	USICNT |= USI16B;					  // shift out 16-bits
    
    _BIS_SR(GIE);
    }
    
    //void delayMillis(unsigned long milliseconds){
    //	// todo: add rollover handling
    //	unsigned long wakeTime = wdtCounter + (milliseconds * WDT_FREQUENCY / 1000);
    //	while(wdtCounter < wakeTime);
    //}
    
    unsigned long locatePeak(unsigned long startTime, unsigned long endTime){
    unsigned long peakTime = 0;
    unsigned long conversionTime;
    unsigned int peakValue = 0;
    unsigned int analogValue;
    
    while(wdtCounter < startTime);
    
    while(wdtCounter < endTime){
    	ADC10CTL0 |= ADC10SC;
    	conversionTime = wdtCounter;
    	while(ADC10CTL1 & ADC10BUSY);
    	analogValue = ADC10MEM;
    	if(analogValue > peakValue){
    		peakValue = analogValue;
    		peakTime = conversionTime;
    	}
    }
    return peakTime;
    }
    
    float wdtTicksToInches(unsigned int ticks){
    return ((ticks / WDT_TICKS_PER_IN) / 2);// + 0.5;
    }
    
    float inchesToWdtTicks(float inches){
    return(inches * WDT_TICKS_PER_IN * 2);
    }
    
    float getDistance(unsigned long minimumWdtTicks, unsigned long maximumWdtTicks){
    unsigned long tStrongestEcho;
    
    sendPing();
    while(TACTL & MC_1);					// wait for ping transmit completion
    tStrongestEcho = locatePeak(minimumWdtTicks + tPing, maximumWdtTicks + tPing);
    
    return wdtTicksToInches(tStrongestEcho - tPing);
    }
    
    void TX_Data(unsigned int data){
    while(USICNT & 0x1F);					// wait for previous TX completion
    USISR = data;
    USICNT += 16;
    }
    
    void main(){
    char iPing;
    float averageDistance;
    unsigned int distance;
    unsigned int minimumWdtTicks;
    unsigned int maximumWdtTicks;
    
    setup();
    
    minimumWdtTicks = inchesToWdtTicks(MINIMUM_DISTANCE_IN);
    maximumWdtTicks = inchesToWdtTicks(MAXIMUM_DISTANCE_IN);
    
    while(1){
    	if(PINGS_AVERAGED > 1){
    		averageDistance = 0;
    		for(iPing = 0; iPing < PINGS_AVERAGED; iPing++)
    			averageDistance += (getDistance(minimumWdtTicks, maximumWdtTicks) / PINGS_AVERAGED);
    
    		distance = averageDistance + 0.5;
    	}
    	else
    		distance = getDistance(minimumWdtTicks, maximumWdtTicks) + 0.5;
    
    	TX_Data(distance);
    }
    
    }
    
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A0 (void){
    if(iTransducerCycle < nTransducerCycles)
    	iTransducerCycle++;
    else{
    	tPing = wdtCounter;
    	stopTransducer();
    	iTransducerCycle = 0;
    }
    }
    
    #pragma vector=WDT_VECTOR
    __interrupt void watchdog_timer(void){
    wdtCounter++;
    }

     

    2011-10-11_17-33-58_573.jpg

  4. If you look at the "application information" section of that datasheet, it shows what pins are connected to the timer A hardware. You're looking for TA0.1 (Timer A0, CCR1) under the "function" column. You'll see your only options are P1.2 and P1.6. I usually try to build my design around the hardware, but if that's not an option, you could use interrupts and software to make it work. It would be a matter of toggling the pin appropriately during the CCR0 and CCR1 ISR's.

     

    To use P1.6, change the instances of BIT2 to BIT6 like you did, but use P1.6, not P1.5. If you really want to use P1.5, this might be a good chance to (re)familiarize yourself with interrupts.

  5. My synth used Timer A in capture mode if you don't mind having to wade through all the unrelated stuff.

     

    viewtopic.php?f=9&t=513&start=10#p5281

     

    I think this is the important part:

     

    P1SEL |= PIN_MIDI_DATA; // Timer A capture input

    TACCTL1 |= CCIE + CAP + CM_3; // enable capture and interrupt on rising and falling edge

     

    ...

     

    // CCR1 capture interrupt. Triggers on both edges, adds fresh midi data

    #pragma vector=TIMERA1_VECTOR

    __interrupt void CCR1_interrupt(void){

    TAR = 0;

    TACCTL0 &= ~CCIFG;

    unsigned int tEdge = TACCR1;

    midiRXBitState = PIN_MIDI_DATA & P1IN;

    TAIV = 0;

     

    addBits(tEdge, !midiRXBitState);

    }

  6. My friend works at a pretty nice coffee shop and he told me the reason you don't store coffee in the fridge is because it acts like baking soda, taking on all the flavors/smells of the other stuff in the fridge. Not entirely related to what you're saying, but maybe somewhat relevant.

  7. I'm a pretty avid gamer. Games I've been playing recently:

    Battlefield Bad Company 2 multiplayer

    CoD Black Ops multiplayer

    Supreme Commander

    Frozen Synapse

     

    I play one or more of those almost daily, and I play a whole mess of other games ranging from Angry Birds to Silent Hunter a little less frequently.

    I refuse to play WoW though, sounds like digital crack.

     

    I've got fairly decent hardware:

    Sandy Bridge i7 2600K overclocked

    8G RAM

    SSD OS disk

    2x physical HDD's in RAID0 for speed

    2x GTX 260's in SLI

    24" 1920x1200 monitor

     

    I claim 0 dependents on my taxes during the year, and often use the resultant tax refund to upgrade my box. I think I'll have to upgrade the GPU's next spring, but they still run most games at max settings/res. It's an expensive hobby for a college student.

  8. Maybe you shouldn't lie to your friends.

     

    Try combining different types of meat. Wrap everything in bacon. Deep fry in oil whenever possible, especially with twinkies and oreos. The goal is to make everything as unhealthy as possible. When making burgers, substitute doughnuts for buns, a very popular dish. Frozen pizza is also very popular. Buy an extra bag of shredded cheese and add that to the frozen pizza. The trick is to cook the pizza half-way and then add the cheese. The secret to flavor is calories. I'm serious about that!

     

    You're welcome.

  9. I guess there would be two stages to the selection: first selecting the part, and then selecting the user who will write the driver for it. The voting system seems like it would be good for selecting the part. Then, if multiple users want the chance to get the part and author the code, maybe the "thanks" leader-boards could be used to make the selection. It could be a reward for the most helpful users. RobG and zeke are high up in the toplist, and I think that really reflects their skill and helpfulness. This system might be discouraging to new members, however.

×
×
  • Create New...