-
-
Save mindcruzer/d03bff36c1be28dd4dc8 to your computer and use it in GitHub Desktop.
#include <intrinsics.h> | |
#include <stdint.h> | |
#include <msp430.h> | |
#define TRIGGER_PIN BIT1 // P6.1 | |
#define ECHO_PIN BIT3 // P1.3 | |
#define LED_PIN BIT0 // P1.0 | |
#define DISTANCE_THRESHOLD 60 // cm | |
#define MEASURE_INTERVAL 2048 // ~250 ms | |
void triggerMeasurement() { | |
// Start trigger | |
P6OUT |= TRIGGER_PIN; | |
// Wait a small amount of time with trigger high, > 10us required (~10 clock cycles at 1MHz MCLK) | |
__delay_cycles(10); | |
// End trigger | |
P6OUT &= ~TRIGGER_PIN; | |
} | |
int main(void) { | |
WDTCTL = WDTPW | WDTHOLD; | |
// Configure trigger pin, low to start | |
P6DIR |= TRIGGER_PIN; | |
P6OUT &= ~TRIGGER_PIN; | |
// Configure LED, off to start | |
P1DIR |= LED_PIN; | |
P1OUT &= ~LED_PIN; | |
// Configure echo pin as capture input to TA0CCR2 | |
P1DIR &= ~ECHO_PIN; | |
P1SEL |= ECHO_PIN; | |
// Set up TA0 to capture in CCR2 on both edges from P1.3 (echo pin) | |
TA0CCTL2 = CM_3 | CCIS_0 | SCS | CAP | CCIE; | |
// Set up TA0 to compare CCR0 (measure interval) | |
TA0CCR0 = MEASURE_INTERVAL; | |
TA0CCTL0 = CCIE; | |
// Set up TA0 with ACLK / 4 = 8192 Hz | |
TA0CTL = TASSEL__ACLK | ID__4 | MC__CONTINUOUS | TACLR; | |
uint16_t lastCount = 0; | |
uint32_t distance = 0; | |
for (;;) | |
{ | |
triggerMeasurement(); | |
// Wait for echo start | |
__low_power_mode_3(); | |
lastCount = TA0CCR2; | |
// Wait for echo end | |
__low_power_mode_3(); | |
distance = TA0CCR2 - lastCount; | |
distance *= 34000; | |
distance >>= 14; // division by 16384 (2 ^ 14) | |
if (distance <= DISTANCE_THRESHOLD) | |
{ | |
// Turn on LED | |
P1OUT |= LED_PIN; | |
} | |
else | |
{ | |
// Turn off LED | |
P1OUT &= ~LED_PIN; | |
} | |
// Wait for the next measure interval tick | |
__low_power_mode_3(); | |
} | |
} | |
#pragma vector = TIMER0_A0_VECTOR | |
__interrupt void TIMER0_A0_ISR (void) { | |
// Measure interval tick | |
__low_power_mode_off_on_exit(); | |
TA0CCR0 += MEASURE_INTERVAL; | |
} | |
#pragma vector = TIMER0_A1_VECTOR | |
__interrupt void TIMER0_A1_ISR (void) { | |
// Echo pin state toggled | |
__low_power_mode_off_on_exit(); | |
TA0IV = 0; | |
} |
@beso-eng It's been a long time since I wrote this, but I believe it works out like this:
The timer is clocked at 8192 Hz (increments 8192 times per second).
2048 ticks means 2048 / 8192 = 1/4 of a second, so 250 ms. This means that the first timer interrupt will fire every 250 ms, effectively taking the device out of low power mode, which it enters as the last instruction of the main loop. All this means is that the main loop runs every 250 ms, so a distance measurement is executed about 4 x per second.
distance = TA0CCR2 - lastCount
This is determining how many times the timer incremented between the trigger (emission of the sound pulse) and the echo (return of the sound pulse).
distance *= 34000
The speed of sound in dry air at room temperature is about 340 m/s. I wanted centimeters here so multiplying by 100 we get 34000 cm/s.
distance >>= 14
Those increments from earlier need to be converted to seconds. Dividing by 8192 (>> 13) gives us seconds, but the sound pulse hits the distant object and then returns, so that time needs to be divided by 2 (>> 14).
The calculation is effectively:
distance = timer ticks * 1 second / 8192 ticks * 1/2 * 34000 cm/s
i have a question please
why to set the MEASURE_INTERVAL to 2048
and could you explain the following equation i didn't get exactly how to find the distance from this equation
distance *= 34000;
distance >>= 14; // division by 16384 (2 ^ 14)
i know that distance = duration * 0.034/2;