diff --git a/labnotes/Lab 5 and 6.out b/labnotes/Lab 5 and 6.out new file mode 100644 index 0000000..e69de29 diff --git a/labnotes/Lab 5 and 6.pdf b/labnotes/Lab 5 and 6.pdf new file mode 100644 index 0000000..d664fb4 Binary files /dev/null and b/labnotes/Lab 5 and 6.pdf differ diff --git a/labnotes/Lab 5 and 6.tex b/labnotes/Lab 5 and 6.tex new file mode 100644 index 0000000..bd48e2a --- /dev/null +++ b/labnotes/Lab 5 and 6.tex @@ -0,0 +1,100 @@ +\documentclass[letterpaper]{article} +\author{Jonathan Chan (15354146)} +\title{PHYS 319\\Labs 5 and 6 Notes} + +\usepackage{fullpage} +\usepackage{minted} +\usepackage{siunitx} +\usepackage{hyperref} + +\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} +\end{document} \ No newline at end of file