Jump to content
Sign in to follow this  
xina

MSP430F5529 Interrupts messing with Ultrasonic Sensor pulseIn() function

Recommended Posts

Hello! So I'm building a robot that is eventually supposed to implement an autonomous functionality, which means obstacle avoidance. I'll be using the HC-SR04 as the ultrasonic sensor of choice. I started out by verifying that the sensor works by running it using Energia, which is the standard "loop infinitely and take a measurement every so many microseconds". In my actual application, however, I want to send out a pulse on command. So when I say so, the ultrasonic will do a measurement (or an average of a few measurements) to tell me if an object is in the path of my robot or not.

 

My actual code is a combination of C (my main function) and a modification of the original Energia project I started with, whose functionality I call from my main application. In my application I'm using uart interrupts on both A0 and A1, and when a certain character is received by A1 I want to access the ultrasonic sensor and take a reading to see if there is an object in the way of my robot or not. There are a few issues that I've been having. The first is that the micros() function doesn't work, so I've taken to making my own delays by using a volatile integer and burning clock cycles that way. The main issue that I'm having (and the reason for this post) is that no matter what I do, the pulseIn() does not work properly. I've pasted the relevant code below. Note that the sensors.cpp file was originally made in Energia, then imported into code composer so that it could be integrated with the main.c file.

 

So this is how my code works. In main.c, U1 will receive an 'I' as an interrupt. In this case, I will call the function fwd(). In the fwd() function, I call the function detectUltraFwd(), which is in sensors.cpp. (It's labeled fwd because later there will be a second ultrasonic sensor for the reverse direction). detectUltraFwd() calls detectUltrasonic(int trig, int echo), where "trig" and "echo" are the specific pins where the ultrasonic sensor is connected to the msp. (Note again, this file came from Energia, so it's a little different than a standard code composer c file).

 

The problem arrives at the line with the pulseIn() function, which was taken from Arduino. According to the function, 0 is returned when there was no measured pulse within the specified timeout. I've tried timeout values varying from 100us to 1s, the maximum value for the function, to no avail. This function always returns 0 and I don't know why. I'm not sure if it's even possible to take a single sample using an ultrasonic sensor. I've tried having the detectUltrasonic() function loop a few times in case just the initial reading was zero, but that wasn't it. The conclusion that I've come to is that it has something to do with micros() not working. Since I'm using interrupts, calling micros() will return 0. (Which is why I'm using the volatile integers to pass time. And yes, I am well aware that I need to play around with the timing to get it close enough to the values I want.) So maybe it's possible that I just don't have my loops timed right, but I ran the original Energia infinite loop code using my made up senswait() function and it worked, so I don't think that's the case.

 

Any insight / help with this matter would be appreciated. My initial searches did not show a resolution to this issue.

 

main.c:

#include <msp430.h>
#include <string.h>
#include <stdlib.h>
#include "motors.h" // my file used for motor control
#include "sensors.h" // my file used for sensor control
int sensingDist=46; //cm
int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
    // initialize A0 uart for communication
    P3SEL = BIT3+BIT4;                        // P3.4,5 = USCI_A0 TXD/RXD
    UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
    UCA0CTL1 |= UCSSEL_2;                     // SMCLK
    UCA0BR0 = 9;                              // 1MHz 115200 (see User's Guide)
    UCA0BR1 = 0;                              // 1MHz 115200
    UCA0MCTL |= UCBRS_1 + UCBRF_0;   // Modln UCBRSx=0, UCBRFx=0, over sampling
    UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
    // initialize A1 uart for communication
    P4SEL |= BIT4+BIT5;                       // P4.4,5 = USCI_A1 TXD/RXD
    UCA1CTL1 |= UCSWRST;                      // **Put state machine in reset**
    UCA1CTL1 |= UCSSEL_2;                     // SMCLK
    UCA1BR0 = 9;                              // 1MHz 115200 (see User's Guide)
    UCA1BR1 = 0;                              // 1MHz 115200
    UCA1MCTL |= UCBRS_1 + UCBRF_0;   // Modln UCBRSx=0, UCBRFx=0,
    UCA1CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCA1IE |= UCRXIE;                         // Enable USCI_A1 RX interrupt
    // Set the pinout for the motor controller.
    setup(); // see motors.h
    P1DIR |= 0x01; // set blue led as output 1.0
    P4DIR |= 0x80; // set green led as output 4.7
    P4OUT |= 0x80; // turn on green led
    P1OUT &= ~0x01; // turn off blue led
    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, interrupts enabled
    __no_operation();                         // For debugger
}
// lots of irrelevant code was removed, including the A0 interrupt.
// USCI_A1 interrupt -- bluetooth module (or terminal if debugging)
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A1_VECTOR))) USCI_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(UCA1IV)
  {
    case 0:break; // no interrupt
    case 2: // RXIFG - received a character!
        if('I' == UCA1RXBUF)
         {
            // Move forward
            fwd();
         }
        break;
    case 4: break; // TXIFG - sending a character
     default: break;
  }
}
void fwd()
{
        // Check to see if there's an object in the way
    int dist = detectUltraFwd();
    if(dist > sensingDist) // if the returned distance is greater than sensingDist, we can freely move forward.
    {
        forward(rotateSpeedFB, rotateLengthFB); // see motors.h - tells the robot to move forward.
    }
    else // otherwise the ultrasonic sensor has detected an object in the way. blink the blue led a couple times as an indication.
    {
        toggleBlue();
        volatile int c = 0;
        for(c=0; c<10000; c++);
        toggleBlue();
        for(c=0; c<10000; c++);
        toggleBlue();
        for(c=0; c<10000; c++);
        toggleBlue();
        for(c=0; c<10000; c++);
        toggleBlue();
    }
}

sensors.cpp

#include "Energia.h"
#include "sensors.h"
const int ultraTrigFwd = P3_5;
const int ultraEchoFwd = P3_6;
int detectUltraFwd()
{
    return detectUltrasonic(ultraTrigFwd, ultraEchoFwd);
}
//ultrasonic function
int detectUltrasonic(int trig, int echo)
{
    long duration, cm;
     // set pin as output
     pinMode(trig, OUTPUT);
    // set it low & wait 2us - in order to get a clean signal.
    digitalWrite(trig, LOW);
    senswait(3);
    // Then set it high for 5 us - i.e. begin taking the measurement.
    digitalWrite(trig, HIGH);
    senswait(10);
    digitalWrite(trig, LOW); // now stop taking the measurement
    //setting up input pin, and receiving the duration in microseconds
    pinMode(echo, INPUT);
    duration  = pulseIn(echo, HIGH, 1000); // *** THIS RIGHT HERE ALWAYS RETURNS ZERO ***
    cm = microSecondsToCentimeter(duration);
    return cm;
}
long microSecondsToCentimeter(long microseconds)
{
    //The speed of sound is 340 m/s or 29 microseconds per centimeter.
    //Convert speed
    return microseconds/29/2;
}
// This function is being used since micros() will always return zero. So I'm burning clock cycles this way.
void senswait(int delay)
{
    for(int i=0; i<delay; i++) {
        volatile unsigned int x;
        x = 5000;
        do x--;
        while(x !=0);
    }
}

If there are small issues like a missing function declaration or header or something, it's because I've had to remove the rest of my project that was irrelevant to my question; my entire code does compile and run!

 

Last notes: the puleIn() function comes directly from Energia. My suspicion is that is somehow is using time, though I did take a look at it and between the bitmasks and counting I didn't see an explicit call to micros() but I'm not sure. All I know is that pulseIn() always returns zero even when I know it shouldn't be.

 

Also if I've violated some rule or completely missed another forum post that's relevant please nudge me in the right direction. And thanks in advance for any help!

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
Sign in to follow this  

×