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