Jump to content
guybarash

"spikes" in the ultrasonic reading

Recommended Posts

hi, 

i'm trying to build an array of unltrasonic sensors, i'm currently using two maxbotic sensors on the msp430G2553 launchpad.

i'm switching between them using a mux (MM74HC151 multiplexer)  using ports 1.3,1.4.15  as control for the mux.

 

my problem is that the reading are'nt stable, every few cycles they "jump" to a very low (low number , as in small distance) and gradually climb back to the right value.

i'm clueless why.

ideas?

 

 

the algorithm is

i= 0 

choose sensor i

enable interrupts 

{do nothing x 5} 

measure using interrupts  sensor's PWM

disable interrupts 

send to PC using UART

i++

 

i've attached an example of a spike in both sensors

 

and the full code:

#include <msp430.h>
#include <stdint.h>
#include <stdlib.h>

static const unsigned long smclk_freq = 16000000UL; // SMCLK frequency in hertz
static const unsigned long bps = 9600UL;            // Async serial bit rate


void Outputinit();
static uint32_t upd = 0;                            // Ultrasonic Pulse Duration (500 ns resolution)
                                                    //
#pragma vector = TIMER1_A1_VECTOR                   // Timer 1A vectored interrupt
__interrupt void timer1_a1_isr(void)                //
{                                                   //
    static uint32_t rise = 0;                       // Pulse rise time
    static uint32_t fall;                           // Pulse fall time
                                                    //
    switch(TA1IV) {                                 // TA0IV must be read to reset interrupt
        case 0x02:                                  // 0x02 == CCR1 (capture/compare)
            if(TA1CCTL1 & CCI) {                    // - Rising edge
                rise = TA1CCR1;                     // Save rise time
                fall = 0;                           // Reset fall time
            } else {                                // - Falling edge
                if(rise) {                          // Make sure rising edge has occurred
                                                    // Handle possible pending overflow interrupt
                    if((TA1CTL & TAIFG) && (TA1CCR0 < 0x1000))
                        fall += TA1CCR0;            //
                    fall += TA1CCR1;                // Get fall time, add to overflow time
                    if(!upd) upd = fall - rise;     // Update time if mainline code is ready for it
                    rise = 0;                       // Clear rise time to ensure next rising edge is used
                }                                   //
            }                                       //
            break;                                  //
        case 0x0A:                                  // 0x0A == TAIFG (overflow)
            fall += TA1CCR0;                        // Update overflow time
            break;                                  //
    }                                               //
}                                                   //

void putc(const unsigned c)                         // Output single char to serial
{                                                   //
    while(!(IFG2 & UCA0TXIFG));                     // Wait for ready (not busy)
    IFG2 &= ~UCA0TXIFG;                             // Reset busy flag
    UCA0TXBUF = c;                                  // Tx char
}                                                   //
                                                    //
void puts(const char *s) { while(*s) putc(*s++); }  // Output string to serial
                                                    //
void print_u32(uint32_t n, const unsigned dp)       // Print 32 bit unsigned with optional decimal place
                                                    // 6 decimal digits (0 -> 999999)
{                                                   //
    unsigned c;                                     //
    c = '0'; while(n >= 100000UL) n -= 100000UL, ++c; putc(c);
    if(dp == 5) putc('.');                          //
    c = '0'; while(n >= 10000) n -= 10000, ++c; putc(c);
    if(dp == 4) putc('.');                          //
    c = '0'; while(n >= 1000) n -= 1000, ++c; putc(c);
    if(dp == 3) putc('.');                          //
    c = '0'; while(n >= 100) n -= 100, ++c; putc(c);
    if(dp == 2) putc('.');                          //
    c = '0'; while(n >= 10) n -= 10, ++c; putc(c);  //
    if(dp == 1) putc('.');                          //
    c = '0'; while(n) --n, ++c; putc(c);            //
}                                                   //

uint32_t ReadSensor() {
	int nop = 0;
	while (nop++ < 5) {}

	upd = 0;
	_enable_interrupts();
	while (upd == 0) {}
	void _disable_interrupts();
	return upd;
}


uint32_t ReadSensorNumber(int j) {   // chooses the j sensor and read from it
										// LSB : 1.3   MSB: 1.5



	if (j == 0) {
	 P1OUT &= 0xc7;
	 }
	else if (j== 1)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x08;
	 }
	else if (j== 2)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x10;
	 }
	else if (j== 3)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x18;
	 }
	else if (j== 4)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x20;
	 }
	else if (j== 5)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x28;
	 }
	else if (j== 6)
	 {
		 P1OUT &= 0xc7;
		 P1OUT |= 0x30;
	 }
	else if (j== 7)
	  {
		 P1OUT &= 0xc7;
	 	 P1OUT |= 0x38;
	  }

	return ReadSensor();
}




void main(void)                                     //
{                                                   //
    WDTCTL = WDTPW | WDTHOLD;                       // Disable watchdog reset
    DCOCTL = 0;                                     // Run at 16 MHz
    BCSCTL1 = CALBC1_16MHZ;                         //
    DCOCTL = CALDCO_16MHZ;                          //
                                                    //
    P1DIR = BIT2;                                   // Setup GPIO
    P1SEL  = BIT1 | BIT2;                           // UART
    P1SEL2 = BIT1 | BIT2;                           //
                                                    //
    P2OUT = 0;                                      // Comperison is done on port 2.1
    P2DIR = BIT0;                                   // Timer 1 capture/compare IO
    P2SEL = BIT0 | BIT1;                            //
    P2SEL2 = 0;                                     //
                                                    //
    const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor
    UCA0CTL1 = UCSWRST;                             // Hold USCI in reset to allow configuration
    UCA0CTL0 = 0;                                   // No parity, LSB first, 8 bits, one stop bit, UART (async)
    UCA0BR1 = (brd >> 12) & 0xFF;                   // High byte of whole divisor
    UCA0BR0 = (brd >> 4) & 0xFF;                    // Low byte of whole divisor
    UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16;        // Fractional divisor, oversampling mode
    UCA0CTL1 = UCSSEL_2;                            // Use SMCLK for bit rate generator, release reset
                                                    //
                                                    // Timer 1 compare 0
    TA1CCR0 = (16000000UL / (8 * 2 * 20)) - 1;      // 20 Hz (50 ms)
    TA1CCTL0 = OUTMOD_4;                            // Toggle mode
                                                    // Timer 1 capture 1
    TA1CCTL1 = CM_3 | SCS | CAP | CCIE;             // Rising and falling, sync, capture, interrupt
                                                    // Timer 1 config
    TA1CTL = TASSEL_2 | ID_3 | MC_1 | TAIE;         // SMCLK, /8, count up, overflow interrupt
                                                    //
                               // Enable interrupts


    Outputinit();								// enables the mux chooser.


    //*													THIS IS START																				**//

    int i= 0;
    uint32_t buff[8];
    while(1){

    buff[i] = 0;
    puts("     <");
    buff[i] += ReadSensorNumber(i);
    print_u32(buff[i], 0);

    puts("> 					");
    i++;
    if (i > 1) {
    	puts("\r\n");
    	i = 0;

    }


    //*													THIS IS END																				**//
    }
}






void Outputinit() {
	P1DIR |= BIT3 + BIT4 + BIT5; // Set the LEDs on P1.0, P1.6 as outputs
	P1OUT = BIT0; // Set P1.0
	return ;
}






thx

 

 

 

post-37215-0-59331300-1406128948_thumb.jpg

Share this post


Link to post
Share on other sites

my problem is that the reading are'nt stable, every few cycles they "jump" to a very low (low number , as in small distance) and gradually climb back to the right value.

i'm clueless why.

ideas?

Turning off interrupts does not stop the timer output from toggling. So you are enabling the next sensor at some time within the timer period. The exact time will keep shifting in and out of sync.

 

The fix is to change the sensor mux in the timer overflow interrupt when the output is low.

 

Give this a try...

 

#include <msp430.h>
#include <stdint.h>

static const unsigned long smclk_freq = 16000000UL; // SMCLK frequency in hertz
static const unsigned long bps = 9600UL;            // Async serial bit rate

static uint32_t upd = 0;                            // Ultrasonic Pulse Duration (500 ns resolution)
static unsigned cur_sen = 7;                        // Current sensor being used
                                                    //
#pragma vector = TIMER1_A1_VECTOR                   // Timer 1A vectored interrupt
__interrupt void timer1_a1_isr(void)                //
{                                                   //
    static uint32_t rise = 0;                       // Pulse rise time
    static uint32_t fall;                           // Pulse fall time
                                                    //
    switch(TA1IV) {                                 // TA0IV must be read to reset interrupt
        case 0x02:                                  // 0x02 == CCR1 (capture/compare)
            if(TA1CCTL1 & CCI) {                    // - Rising edge
                rise = TA1CCR1;                     // Save rise time
                fall = 0;                           // Reset fall time
            } else {                                // - Falling edge
                if(rise) {                          // Make sure rising edge has occurred
                                                    // Handle possible pending overflow interrupt
                    if((TA1CTL & TAIFG) && (TA1R < 0x1000))
                        fall += TA1CCR0;            //
                    fall += TA1CCR1;                // Get fall time, add to overflow time
                    if(!upd) upd = fall - rise;     // Update time if mainline code is ready for it
                    rise = 0;                       // Clear rise time to ensure next rising edge is used
                }                                   //
            }                                       //
            break;                                  //
        case 0x0A:                                  // 0x0A == TAIFG (overflow)
            fall += TA1CCR0;                        // Update overflow time
            if(P2IN & BIT0) {                       // If output is high
                ++cur_sen;                          //  increment current sensor
                cur_sen &= 7;                       //
            } else {                                // If output is low
                                                    //  set mux to next sensor
                P1OUT = (P1OUT & ~(BIT3 | BIT4 | BIT5)) | (((cur_sen + 1) << 3) & (BIT3 | BIT4 | BIT5));
            }                                       //
            break;                                  //
    }                                               //
}                                                   //

void putc(const unsigned c)                         // Output single char to serial
{                                                   //
    while(!(IFG2 & UCA0TXIFG));                     // Wait for ready (not busy)
    IFG2 &= ~UCA0TXIFG;                             // Reset busy flag
    UCA0TXBUF = c;                                  // Tx char
}                                                   //
                                                    //
void puts(const char *s) { while(*s) putc(*s++); }  // Output string to serial
                                                    //
void print_u32(uint32_t n, const unsigned dp)       // Print 32 bit unsigned with optional decimal place
                                                    // 6 decimal digits (0 -> 999999)
{                                                   //
    unsigned c;                                     //
    c = '0'; while(n >= 100000UL) n -= 100000UL, ++c; putc(c);
    if(dp == 5) putc('.');                          //
    c = '0'; while(n >= 10000) n -= 10000, ++c; putc(c);
    if(dp == 4) putc('.');                          //
    c = '0'; while(n >= 1000) n -= 1000, ++c; putc(c);
    if(dp == 3) putc('.');                          //
    c = '0'; while(n >= 100) n -= 100, ++c; putc(c);
    if(dp == 2) putc('.');                          //
    c = '0'; while(n >= 10) n -= 10, ++c; putc(c);  //
    if(dp == 1) putc('.');                          //
    c = '0'; while(n) --n, ++c; putc(c);            //
}                                                   //

void main(void)                                     //
{                                                   //
    WDTCTL = WDTPW | WDTHOLD;                       // Disable watchdog reset
    DCOCTL = 0;                                     // Run at 16 MHz
    BCSCTL1 = CALBC1_16MHZ;                         //
    DCOCTL = CALDCO_16MHZ;                          //
                                                    //
    P1DIR = BIT2 | BIT3 | BIT4 | BIT5;              // Setup GPIO
    P1SEL  = BIT1 | BIT2;                           // UART
    P1SEL2 = BIT1 | BIT2;                           //
                                                    //
    P2OUT = 0;                                      //
    P2DIR = BIT0;                                   // Timer 1 capture/compare IO
    P2SEL = BIT0 | BIT1;                            //
    P2SEL2 = 0;                                     //
                                                    //
    const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor
    UCA0CTL1 = UCSWRST;                             // Hold USCI in reset to allow configuration
    UCA0CTL0 = 0;                                   // No parity, LSB first, 8 bits, one stop bit, UART (async)
    UCA0BR1 = (brd >> 12) & 0xFF;                   // High byte of whole divisor
    UCA0BR0 = (brd >> 4) & 0xFF;                    // Low byte of whole divisor
    UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16;        // Fractional divisor, oversampling mode
    UCA0CTL1 = UCSSEL_2;                            // Use SMCLK for bit rate generator, release reset
                                                    //
                                                    // Timer 1 compare 0
    TA1CCR0 = 64000;                                // 64 ms
    TA1CCTL0 = OUTMOD_4;                            // Toggle mode
                                                    // Timer 1 capture 1
    TA1CCTL1 = CM_3 | SCS | CAP | CCIE;             // Rising and falling, sync, capture, interrupt
                                                    // Timer 1 config
    TA1CTL = TASSEL_2 | ID_3 | MC_1 | TAIE;         // SMCLK, /8, count up, overflow interrupt
                                                    //
    _enable_interrupts();                           // Enable interrupts
                                                    //
    for(; {                                       // For-ever
        if(upd) {                                   // Check for pulse duration measuement available
                                                    // Calculate inches
            const uint32_t in = ((upd * 5534) + (upd >> 1)) >> 14;
                                                    // Calculate mm
            const uint32_t mm = (upd * 5623) >> 16;
                                                    //
            putc('0' + cur_sen);                    // Print current sensor #
            putc(' ');                              //
            print_u32(in, 2);                       // Print inches
            puts(" in  ");                          //
            print_u32(mm, 0);                       // Print mm
            puts(" mm");                            //
            puts("\r\n");                           //
            upd = 0;                                // Ready for next
        }                                           //
    }                                               //
}                                                   //

Share this post


Link to post
Share on other sites

thx alot.  (the code commets are very helpful :-)  )

the spikes have gone , stil lots of static noise

 i'm thinking maybe the sensors aren't accurate at a distance of 2+ meters (the issue still exist with 1 sensor and no switching)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×