{ "metadata": { "gist_id": "5120353", "name": "Measuring g with an inclined plane" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "from IPython.display import display, Latex, Math" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import phm" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "p = phm.phm()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "bin(p.read_inputs())" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def shutup():\n", " p.set_frequency(0)\n", " p.write_outputs(0b1000)\n", "\n", "def shutup_handler(self, etype, value, tb, tb_offset=None):\n", " shutup()\n", " print 'KeyboardInterrupt'\n", "\n", "get_ipython().set_custom_exc((KeyboardInterrupt,), shutup_handler)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def notify_speaker():\n", " p.set_frequency(50)\n", "\n", "def notify_led():\n", " p.set_voltage(3000)\n", "\n", "notify = notify_speaker" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "p.write_outputs(0b1000)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "test the photo gate" ] }, { "cell_type": "code", "collapsed": false, "input": [ "f = 0\n", "stepup = 20\n", "stepdown = stepup * 3\n", "dt = 0.1\n", "fmax = 550\n", "nmax = 15\n", "nmin = 0\n", "while True:\n", " d = p.read_inputs()\n", " if d is None:\n", " continue\n", "\n", " if d & 0b1000:\n", " f += stepup\n", " f = min(f, fmax)\n", " else:\n", " f -= stepdown\n", " f = max(0,f)\n", " p.set_frequency(f)\n", " p.write_outputs(int(1.*f * nmax / fmax))\n", " time.sleep(dt)\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Activate the magnet" ] }, { "cell_type": "code", "collapsed": false, "input": [ "p.write_outputs(0b1110)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def magnetize():\n", " p.write_outputs(0b1000)\n", "\n", "def drop():\n", " p.write_outputs(0b0010)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "magnetize()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we measure time:\n", " \n", "- drop the ball\n", "- poll the light barrier for when the ball crosses its path" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def wait(beats=3):\n", " time.sleep(beats * 60. / tempo)\n", "\n", "C4 = 130.81\n", "def ready_beep(beats=1):\n", " p.write_outputs(0b1100)\n", " p.set_frequency(C4)\n", " wait(beats)\n", " p.write_outputs(0b1000)\n", " p.set_frequency(0)\n", "\n", "def go_beep(beats=1):\n", " p.write_outputs(0b1010)\n", " p.set_frequency(C4*2)\n", " wait(beats)\n", " p.set_frequency(0)\n", "\n", "def catch_beep(beats=1):\n", " p.write_outputs(0b1110)\n", " p.set_frequency(C4*4)\n", " wait(beats)\n", " p.set_frequency(0)\n", " p.write_outputs(0b000)\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "tempo = 600" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def gate_blocked():\n", " mask = None\n", " while mask is None:\n", " mask = p.read_inputs()\n", " return (mask & 0b1000)\n", " " ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def time_drop():\n", " print \"waiting for signal ...\",\n", " sys.stdout.flush()\n", " while not gate_blocked():\n", " time.sleep(0.1)\n", " print \"ready ...\",\n", " sys.stdout.flush()\n", " while gate_blocked():\n", " ready_beep()\n", " wait(4)\n", " go_beep(3)\n", " print \"go!\"\n", " sys.stdout.flush()\n", " start = time.time()\n", " drop()\n", " cycles = 0\n", " while not gate_blocked():\n", " cycles += 1\n", " stop = time.time()\n", " t = stop - start\n", " err = 0.5 * t / cycles\n", " t -= err\n", " tms = 1e3*t\n", " print u\"%i \u00b1 %.1f ms\" % (1e3 * t, 1e3 * err)\n", " catch_beep()\n", " magnetize()\n", " return t, err" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "time_drop()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%pylab inline" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "ds = [0, 10, 15, 20, 25]\n", "ts = [0]\n", "errs = [0]\n", "\n", "for d in ds[1:]:\n", " print \"move magnet to %i cm\" % d\n", " t, err = time_drop()\n", " ts.append(t)\n", " errs.append(err)\n", "\n", "ds = np.array(ds)\n", "ts = np.array(ts)\n", "errs = np.array(errs)\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "plot(ds, ts, '-o')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we have the force pulling the ball down the incline:\n", " \n", "\n", "$F = mg$ $sin(\\theta)$\n", "\n", "And the distance to the bottom $d$.\n", "The position of the ball along the plane is described by\n", " \n", "$\\ddot x = g$ $sin(\\theta)$\n", "\n", "Which we can integrate with the initial conditions\n", "\n", "$x(0) = \\dot x(0) = 0$\n", "\n", "so we get\n", "\n", "$\\dot x = gt$ $sin(\\theta)$\n", "\n", "$x(t) = \\frac{1}{2} g t^2$ $sin(\\theta)$\n", "\n", "And we are measuring $t$ where $x(t) = d$,\n", "so we have the equation\n", "\n", "$d = \\frac{1}{2} g t^2$ $sin(\\theta)$\n", "\n", "where $d$ is known and $t$ is measured,\n", "so we now have a relationship for $g$ and $\\theta$:\n", " \n", "$sin(\\theta) = \\frac{2 d}{g t^2}$\n", "\n", "$g = \\frac{2 d}{ t^2 sin(\\theta)}$\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From our measurements of $t$ and $d$,\n", "we can get an expression for $g$ $sin(\\theta)$\n", "by doing a least-squares fit for a second order polynomial,\n", "of the form:\n", " \n", "$d = a t^2$\n", "\n", "where\n", "\n", "$a = \\frac{1}{2} g$ $sin(\\theta)$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "plot(ts, ds, '-o')\n", "xlabel(\"t\")\n", "ylabel(\"d\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now do a least-squares fit for $a$ in\n", "\n", "$d = a t ^ 2$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from scipy.optimize import leastsq\n", "\n", "err_f = lambda a: a*ts*ts - ds\n", "\n", "a = leastsq(err_f, 1)[0][0]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%config InlineBackend.figure_format = 'svg'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "tt = np.linspace(0, ts[-1])\n", "plot(tt, a * tt**2, '-', ts, ds, '-o');" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and\n", "\n", "$g$ $sin(\\theta) = 2 a$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "g_sin_theta = 2 * a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we measure the elevation of the 30cm mark,\n", "we can get\n", "\n", "$sin(\\theta) = \\frac{h}{30cm}$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "sin_theta = 2.2 / 30" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which we can now plug into the above equation,\n", "solving for $g$\n", "\n", "$g = \\frac{2 a} {sin(\\theta)}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "which will hopefully be close to the true value of $g_{true} = 980.7$\n", "\n", "With our error $\\Delta g$:\n", " \n", "$\\Delta g = \\frac{g - g_{true}}{g_{true}}$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "g = g_sin_theta / sin_theta\n", "\n", "display(Latex(\"$g = %.1f$ cm/s\" % g))\n", "\n", "g_true = 980.7\n", "dg = (g - g_true) / g_true\n", "display(Latex(\"$g_{true} = %.1f$ cm/s\" % g_true))\n", "display(Latex(r\"error $= %.1f$ %%\" % (100*dg)))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }