108 lines
7.1 KiB
TeX
108 lines
7.1 KiB
TeX
\documentclass[letterpaper]{article}
|
|
\author{Jonathan Chan (15354146)}
|
|
\title{PHYS 319\\Labs 5 and 6 Notes}
|
|
|
|
\usepackage{fullpage}
|
|
\usepackage{minted}
|
|
\usepackage{siunitx}
|
|
\usepackage{hyperref}
|
|
\usepackage{graphicx}
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
|
|
The goal of this lab is to measure distances with the ultrasonic ranger. References to specific values and other documentation notes refer to \url{http://www.robot-electronics.co.uk/htm/srf04tech.htm}. The steps to achieve this can be outlined as follows:
|
|
\begin{enumerate}
|
|
\item Send a trigger pulse to the ranger. According to the documentation, this pulse needs to be $\SI{10}{\micro s}$ long.
|
|
\item Wait for the echo input to be raised. This can be done by setting a low-to-high interrupt on the echo pin.
|
|
\item Time the length of the echo pulse sent by the ranger. We will set \texttt{TAR} to 0 and retrieve the value of \texttt{TAR} when the echo pin is lowered, which can be done by setting a high-to-low interrupt on the echo pin. We will use the SMCLK timer, which runs at $\SI{1}{M\hertz}$, meaning that the maximum length that can be measured without overflowing is $\SI{65 535}{\micro s}$. However, according to the documentation, the ranger will time out and lower the echo pin after $\SI{30 000}{\micro s}$, so we aren't in danger of overflowing.
|
|
\item Convert the measurement to distance in centimetres. According to the documentation, we need to divide by $58$. Since we're limited to sending one byte at a time, we can also set the value to $0$ if the distance exceeds $\SI{255}{cm}$ to prevent the plot from graphing meaningless overflowed values.
|
|
\item Send the data to the Python plot. This portion of the code will come from the provided temperature measurement program.
|
|
\item Repeat the measurement. According to the documentation, we need to wait $\SI{10}{ms}$ to allow the ranger to recharge. I've set the delay to $\SI{100}{ms}$ to smooth out the data and prevent rapid changes in the position of the ranger from being recorded.
|
|
\end{enumerate}
|
|
With some measurements using a metre stick, the distances measured by the ranger are indeed accurate to the centimetre. It also appears that it cannot measure anything closer than $\SI{3}{cm}$. Of course, we are also upper-bounded at $\SI{255}{cm}$ by the size of one byte, even if the limit of the ranger itself is $\SI{30 000}{\micro s} / \SI{58}{\micro s*cm^{-1}} \approx \SI{517}{cm}$. We can circumvent this by dividing the the value by $2$ in the C program then multiplying it by $2$ again in the Python program, so that the maximum measurable distance is $\SI{510}{cm}$, at the cost of decreasing the precision to a granularity of $\SI{2}{cm}$.
|
|
|
|
Below is the modified \texttt{main.c} file, with the remaining files unchanged from \url{http://www.phas.ubc.ca/~michal/phys319/temperature_demo4.zip}. Of course, the axis ranges and labels of the plot should be adjusted accordingly. After the C program has been written to the microprocessor, connect P1.4 to the ranger's trigger pin, connect P1.6 to the ranger's echo pin through a $\SI{1}{k\ohm}$ resistor, connect the ranger to $\SI{5}{V}$ and ground, connect the microprocessor to ground, and run \texttt{python python-serial-plot.py}.
|
|
|
|
\newpage
|
|
\noindent \textit{\texttt{main.c}}:
|
|
\begin{minted}{c}
|
|
#include "msp430.h"
|
|
#define TXD BIT2
|
|
#define RXD BIT1
|
|
#define TRIG BIT4
|
|
#define ECHO BIT6
|
|
#define CM 58
|
|
|
|
unsigned int TXByte;
|
|
void main(void) {
|
|
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
|
|
|
|
BCSCTL1 = CALBC1_1MHZ; // Set range
|
|
DCOCTL = CALDCO_1MHZ;
|
|
BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1 MHz
|
|
P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
|
|
P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
|
|
UCA0CTL1 |= UCSSEL_2; // Use SMCLK
|
|
UCA0BR0 = 104; // Set baud rate to 9600 with 1MHz clock (Data Sheet 15.3.13)
|
|
UCA0BR1 = 0; // Set baud rate to 9600 with 1MHz clock
|
|
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
|
|
UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine
|
|
|
|
P1DIR |= TXD;
|
|
P1OUT |= TXD;
|
|
P1DIR |= TRIG; // set trigger output
|
|
P1DIR &= ~ECHO; // set echo input
|
|
P1IE |= ECHO; // use echo input as interrupt
|
|
TACTL = TACLR; // reset clock
|
|
TACTL = TASSEL_2 | MC_2; // set SMCLK timer to count up at 1 MHz
|
|
__enable_interrupt();
|
|
|
|
while (1) {
|
|
P1OUT |= TRIG; // start trigger signal
|
|
__delay_cycles(10); // we need a >10 us pulse and one clock cycle is 1 us
|
|
P1OUT &= ~TRIG; // end trigger signal
|
|
|
|
P1IES &= ~ECHO; // interrupt on low to high
|
|
__bis_SR_register(LPM0_bits + GIE);
|
|
TAR = 0;
|
|
P1IES |= ECHO; // interrupt on high to low
|
|
__bis_SR_register(LPM0_bits + GIE);
|
|
|
|
TXByte = TAR / CM; // distance in cm
|
|
TXByte = (TXByte <= 0xFF) * TXByte; // set to 0 if beyond range
|
|
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer to be ready for new data
|
|
UCA0TXBUF = TXByte;
|
|
|
|
__delay_cycles(100000); // wait >10 ms before measuring again
|
|
}
|
|
}
|
|
|
|
// handle P1.3 interrupts
|
|
#if defined(__TI_COMPILER_VERSION__)
|
|
#pragma vector=PORT1_VECTOR
|
|
__interrupt void port1_isr(void)
|
|
#else
|
|
void __attribute__ ((interrupt(PORT1_VECTOR))) port1_isr (void)
|
|
#endif
|
|
{
|
|
P1IFG = 0; // reset interrupt flag
|
|
__bic_SR_register_on_exit(LPM0_bits); // take us out of low power mode
|
|
}
|
|
\end{minted}
|
|
|
|
\noindent \textit{\texttt{serial-python-plot.py}}:
|
|
\begin{minted}{python}
|
|
...
|
|
ax = fig.add_subplot(111,xlabel='Time Step',ylabel='Distance (cm)')
|
|
ax.set_ylim(0,255) # set limits of y axis.
|
|
...
|
|
\end{minted}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{ranger-measurement}
|
|
\end{figure}
|
|
|
|
The above chart shows the deviation from the actual distance as measured with the ultrasonic ranger by pointing it at a perpendicular wall certain distances away. The measurements for distances under $\SI{3}{cm}$ are all exactly $\SI{3}{cm}$, which explains the linearly decreasing distances in the lower end; as mentioned previously, the ranger cannot measure distances any closer. As distance increases, the measurement becomes less accurate: this may be because the father the pulse has to travel, the more spread out it becomes, and it bounces off parts of the wall not exactly perpendicular but slightly off centre. This explanation is further supported by the fact that when using a portable smaller surface in lieu of a wall, as I had originally done, at certain distances the surface wasn't large enough to yield a meaningful result.
|
|
\end{document} |