guybarash 0 Posted July 23, 2014 Share Posted July 23, 2014 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 Quote Link to post Share on other sites
David Bender 28 Posted July 23, 2014 Share Posted July 23, 2014 Why are you comparing TA1CCR0 to a constant? You set it only once in the code and never change it again... if((TA1CTL & TAIFG) && (TA1CCR0 < 0x1000)) fall += TA1CCR0; oPossum 1 Quote Link to post Share on other sites
oPossum 1,083 Posted July 23, 2014 Share Posted July 23, 2014 Should be TA1R instead of TA1CCR. Thanks for finding that bug. Quote Link to post Share on other sites
oPossum 1,083 Posted July 23, 2014 Share Posted July 23, 2014 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 } // } // } // Quote Link to post Share on other sites
guybarash 0 Posted July 27, 2014 Author Share Posted July 27, 2014 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) Quote Link to post Share on other sites
oPossum 1,083 Posted July 27, 2014 Share Posted July 27, 2014 Using a 74HC238 to limit transmission to only one module may be helpful. With all of them sending all of the time there may be problems with echos from the transmissions of other modules. abecedarian 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.