<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://shawnreeves.net//wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Shawn</id>
	<title>ShawnReevesWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://shawnreeves.net//wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Shawn"/>
	<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Special:Contributions/Shawn"/>
	<updated>2026-04-11T11:52:36Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Python_ball_pits&amp;diff=2949</id>
		<title>Python ball pits</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Python_ball_pits&amp;diff=2949"/>
		<updated>2026-03-01T04:06:07Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;d enjoyed the interactive particles on a screen with a camera I&#039;ve seen at the Museum of Science and other places, and I&#039;ve wanted to program them for years, so as I started to learn Python I used Devstral LLM to jumpstart a program, then added features.&lt;br /&gt;
Here&#039;s the code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
from cv2_enumerate_cameras import enumerate_cameras&lt;br /&gt;
import cv2&lt;br /&gt;
import numpy as np&lt;br /&gt;
import random&lt;br /&gt;
from collections import deque&lt;br /&gt;
import time&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Todo&lt;br /&gt;
Display on frame notice if no cameras found.&lt;br /&gt;
Button for going back to camera selection.&lt;br /&gt;
Convert from global variables to parameters passed to functions.&lt;br /&gt;
Variable particle colors, size, mass&lt;br /&gt;
Sliders/dials for parameters&lt;br /&gt;
Smoothly add/reduce particles&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
# Global variables&lt;br /&gt;
particle_count = 80  # Initial number of particles&lt;br /&gt;
min_area = 500       # Minimum area to consider as motion&lt;br /&gt;
history = 10         # Number of frames for background subtraction&lt;br /&gt;
particles = deque(maxlen=particle_count)&lt;br /&gt;
particle_size = 10&lt;br /&gt;
particle_color = (250, 200, 50) &lt;br /&gt;
motion_objects = []  # List to store motion objects (center, direction)&lt;br /&gt;
damping = 0.9995&lt;br /&gt;
gravity = 0.09&lt;br /&gt;
MAX_MOTION_OBJECTS = 10&lt;br /&gt;
STATES = (&amp;quot;Camera selection&amp;quot;, &amp;quot;Activity&amp;quot;)&lt;br /&gt;
state = 0&lt;br /&gt;
window_size = {&amp;quot;width&amp;quot;:1024,&amp;quot;height&amp;quot;:768}&lt;br /&gt;
&lt;br /&gt;
def capture_still(camera):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Capture a still image from the specified camera on its backend&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    cap = cv2.VideoCapture(camera.index, camera.backend)&lt;br /&gt;
    time.sleep(0.6) # Wait for camera to open before getting snapshot; some short times cause error.&lt;br /&gt;
    #print(&amp;quot;Captured a still&amp;quot;)&lt;br /&gt;
    ret, frame = cap.read()&lt;br /&gt;
    cap.release()&lt;br /&gt;
    return frame&lt;br /&gt;
            &lt;br /&gt;
def display_cameras_and_get_selection(cameras):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Display stills from all cameras and let user select one&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # cameras is a list of CameraInfo objects with properties we&#039;ll use: CameraInfo.name and CameraInfo.index&lt;br /&gt;
    camera_ID = None&lt;br /&gt;
    camera_indices = [camera.index for camera in cameras]&lt;br /&gt;
    #print(f&amp;quot;debug: camera_indices:{camera_indices}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def on_mouse_event_camera_selection(event, x, y, flags, param):&lt;br /&gt;
        nonlocal camera_ID&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Click event during camera selection&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        if event == cv2.EVENT_LBUTTONDOWN:&lt;br /&gt;
            # Get the list of camera indices and their positions&lt;br /&gt;
            camera_indices, positions = param&lt;br /&gt;
            # Check which camera was clicked&lt;br /&gt;
            for i, (cx, cy, cw, ch) in enumerate(positions):&lt;br /&gt;
                if cx &amp;lt;= x &amp;lt;= cx + cw and cy &amp;lt;= y &amp;lt;= cy + ch:&lt;br /&gt;
                    camera_ID = camera_indices[i]&lt;br /&gt;
                    #print(f&amp;quot;on_mouse_event_camera_selection set camera_ID: {camera_ID}&amp;quot;)&lt;br /&gt;
                    return&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Capture stills from all cameras&lt;br /&gt;
    stills = []&lt;br /&gt;
    for camera in cameras:&lt;br /&gt;
        stills.append(capture_still(camera))&lt;br /&gt;
&lt;br /&gt;
    # Create a window to display all stills&lt;br /&gt;
    window_name = &amp;quot;Select Camera&amp;quot;&lt;br /&gt;
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)&lt;br /&gt;
    cv2.resizeWindow(window_name, window_size[&amp;quot;width&amp;quot;], window_size[&amp;quot;height&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
    # Calculate grid layout&lt;br /&gt;
    cols = 4&lt;br /&gt;
    rows = (len(stills) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
    # Prepare to store camera positions&lt;br /&gt;
    camera_positions = []&lt;br /&gt;
&lt;br /&gt;
    # Calculate image size and spacing&lt;br /&gt;
    spacing = 10&lt;br /&gt;
    img_width = (window_size[&amp;quot;width&amp;quot;] - 2*spacing)//cols&lt;br /&gt;
    img_height = img_width * window_size[&amp;quot;height&amp;quot;] // window_size[&amp;quot;width&amp;quot;]&lt;br /&gt;
    #print(img_width, &amp;quot; &amp;quot;, img_height)&lt;br /&gt;
&lt;br /&gt;
    # Create a blank canvas of 1024x768&lt;br /&gt;
    canvas = np.ones((window_size[&amp;quot;height&amp;quot;], window_size[&amp;quot;width&amp;quot;], 3), dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
    # Display all stills in a grid on the canvas&lt;br /&gt;
    for i, still in enumerate(stills):&lt;br /&gt;
        row = i // cols&lt;br /&gt;
        col = i % cols&lt;br /&gt;
&lt;br /&gt;
        # Resize image to 320x240&lt;br /&gt;
        #print(f&amp;quot;Resizing: img_width, img_height:{img_width}, {img_height}&amp;quot;)&lt;br /&gt;
        resized = cv2.resize(still, (img_width, img_height))&lt;br /&gt;
&lt;br /&gt;
        # Calculate position in the grid&lt;br /&gt;
        x = col * (img_width + spacing)&lt;br /&gt;
        y = row * (img_height + spacing)&lt;br /&gt;
&lt;br /&gt;
        # Store camera position for click detection&lt;br /&gt;
        camera_positions.append((x, y, img_width, img_height))&lt;br /&gt;
&lt;br /&gt;
        # Place image on canvas&lt;br /&gt;
        canvas[y:y+img_height, x:x+img_width] = resized&lt;br /&gt;
&lt;br /&gt;
        # Add camera index text&lt;br /&gt;
        cv2.putText(canvas, f&amp;quot;Camera {camera_indices[i]}&amp;quot;, (x+10, y+20),&lt;br /&gt;
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)&lt;br /&gt;
&lt;br /&gt;
    # Display the canvas&lt;br /&gt;
    cv2.imshow(window_name, canvas)&lt;br /&gt;
&lt;br /&gt;
    # Set mouse callback&lt;br /&gt;
    cv2.setMouseCallback(window_name, on_mouse_event_camera_selection, (camera_indices, camera_positions))&lt;br /&gt;
&lt;br /&gt;
    # Wait for user to click on an image&lt;br /&gt;
    last_time=time.time()&lt;br /&gt;
    while True:&lt;br /&gt;
        key = cv2.waitKey(1) &amp;amp; 0xFF&lt;br /&gt;
        if time.time()-last_time &amp;gt; 1.0:&lt;br /&gt;
            last_time = time.time()&lt;br /&gt;
        if key == 27:  # ESC key to exit&lt;br /&gt;
            cv2.destroyAllWindows()&lt;br /&gt;
            return None&lt;br /&gt;
        if camera_ID is not None:&lt;br /&gt;
            cv2.destroyAllWindows()&lt;br /&gt;
            return camera_ID&lt;br /&gt;
&lt;br /&gt;
def activity(camera):    &lt;br /&gt;
    global particle_count&lt;br /&gt;
    global particles&lt;br /&gt;
    class button:&lt;br /&gt;
        def __init__(self, x, y, width, height, title):&lt;br /&gt;
            self.x = x&lt;br /&gt;
            self.y = y&lt;br /&gt;
            self.width = width&lt;br /&gt;
            self.height = height&lt;br /&gt;
            self.title = title&lt;br /&gt;
            self.clicked = False&lt;br /&gt;
        &lt;br /&gt;
    reset_button = button(10,10,100,40,&amp;quot;RESET&amp;quot;)&lt;br /&gt;
    quit_button = button(120,10,100,40,&amp;quot;QUIT&amp;quot;)&lt;br /&gt;
    buttons = [reset_button, quit_button]&lt;br /&gt;
    &lt;br /&gt;
    def on_mouse_click(event, x, y, flags, param):&lt;br /&gt;
        buttons = param&lt;br /&gt;
        if event == cv2.EVENT_LBUTTONDOWN:&lt;br /&gt;
            #print(&amp;quot;mouse clicked&amp;quot;)&lt;br /&gt;
            # Check if click is within the reset button area&lt;br /&gt;
            for button in buttons:&lt;br /&gt;
                if button.x &amp;lt;= x &amp;lt;= button.x+button.width and button.y &amp;lt;= y &amp;lt;= button.y+button.width:&lt;br /&gt;
                #print(&amp;quot;reset clicked&amp;quot;)&lt;br /&gt;
                    button.clicked = True&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def on_particle_count_change(val):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Callback function for particle count trackbar&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particle_count&lt;br /&gt;
        particle_count = val&lt;br /&gt;
    def update_particles(motion_objects):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Update particle positions and accelerate near motion objects&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particles&lt;br /&gt;
&lt;br /&gt;
        for i in range(len(particles)):&lt;br /&gt;
            x, y, dx, dy = particles[i]&lt;br /&gt;
            # Damp motion, more for faster particles&lt;br /&gt;
            dx *= damping/(1+(np.abs(dx)/1000))&lt;br /&gt;
            dy *= damping/(1+(np.abs(dy)/1000))&lt;br /&gt;
            dy += gravity&lt;br /&gt;
    &lt;br /&gt;
            # Check proximity to motion objects&lt;br /&gt;
            for obj in motion_objects:&lt;br /&gt;
                obj_x, obj_y, obj_dx, obj_dy = obj&lt;br /&gt;
                distance = np.sqrt((x - obj_x)**2 + (y - obj_y)**2)&lt;br /&gt;
    &lt;br /&gt;
                # If particle is near a motion object, accelerate in that direction&lt;br /&gt;
                if distance &amp;lt; 100:  # Proximity threshold&lt;br /&gt;
                    # Add motion vector to particle velocity&lt;br /&gt;
                    dx += obj_dx * 1/(distance+2)&lt;br /&gt;
                    dy += obj_dy * 1/(distance+2)&lt;br /&gt;
    &lt;br /&gt;
            # Update position&lt;br /&gt;
            x += dx&lt;br /&gt;
            y += dy&lt;br /&gt;
    &lt;br /&gt;
            # Bounce off edges&lt;br /&gt;
            frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)&lt;br /&gt;
            frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)&lt;br /&gt;
    &lt;br /&gt;
            if x &amp;lt;= 0:&lt;br /&gt;
                dx = np.abs(dx)&lt;br /&gt;
                x=0&lt;br /&gt;
            if x &amp;gt;= frame_width:&lt;br /&gt;
                dx = -1 * np.abs(dx)&lt;br /&gt;
                x = frame_width&lt;br /&gt;
            if y &amp;lt;= 0:&lt;br /&gt;
                dy = np.abs(dy)&lt;br /&gt;
                y=0&lt;br /&gt;
            if y &amp;gt;= frame_height:&lt;br /&gt;
                dy = -1 * np.abs(dy)&lt;br /&gt;
                y = frame_height&lt;br /&gt;
    &lt;br /&gt;
            particles[i] = [x, y, dx, dy]&lt;br /&gt;
&lt;br /&gt;
    def generate_particles(count=particle_count):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Generate particles at random positions&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particles&lt;br /&gt;
        nonlocal cap&lt;br /&gt;
        particles.clear()&lt;br /&gt;
        frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)&lt;br /&gt;
        frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)&lt;br /&gt;
    &lt;br /&gt;
        for _ in range(count):&lt;br /&gt;
            x = random.randint(0, int(frame_width))&lt;br /&gt;
            y = random.randint(0, int(frame_height))&lt;br /&gt;
            dx = random.uniform(-1, 1)  # Random initial velocity&lt;br /&gt;
            dy = random.uniform(-1, 1)&lt;br /&gt;
            particles.append([x, y, dx, dy])&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    # Initialize video capture with selected camera&lt;br /&gt;
    try:&lt;br /&gt;
        cap = cv2.VideoCapture(camera.index, camera.backend)&lt;br /&gt;
        if not cap.isOpened():&lt;br /&gt;
            pass&lt;br /&gt;
            #print(f&amp;quot;camera {camera_index} not available anymore.&amp;quot;)&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        pass&lt;br /&gt;
        #print(f&amp;quot;camera {camera_index} not available anymore. error {ValueError}&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    # Create window and trackbar&lt;br /&gt;
    activityWindowName=&#039;Motion Detection with Particles&#039;&lt;br /&gt;
    cv2.namedWindow(activityWindowName)&lt;br /&gt;
    cv2.createTrackbar(&#039;Particles&#039;, activityWindowName, particle_count, 100, on_particle_count_change)&lt;br /&gt;
    &lt;br /&gt;
    # Initialize background subtractor&lt;br /&gt;
    backSub = cv2.createBackgroundSubtractorMOG2(history, 16, True)&lt;br /&gt;
    &lt;br /&gt;
    # Generate initial particles&lt;br /&gt;
    generate_particles()&lt;br /&gt;
    cv2.setMouseCallback(activityWindowName, on_mouse_click, buttons)&lt;br /&gt;
&lt;br /&gt;
    while True:&lt;br /&gt;
        ret, frame = cap.read()&lt;br /&gt;
        if not ret:&lt;br /&gt;
            continue&lt;br /&gt;
    &lt;br /&gt;
        # Flip the frame horizontally&lt;br /&gt;
        frame = cv2.flip(frame, 1)&lt;br /&gt;
    &lt;br /&gt;
        # Get current particle count from trackbar&lt;br /&gt;
        current_particle_count = cv2.getTrackbarPos(&#039;Particles&#039;, activityWindowName)&lt;br /&gt;
        if current_particle_count != particle_count:&lt;br /&gt;
            particle_count = current_particle_count&lt;br /&gt;
            particles = deque(maxlen=particle_count)&lt;br /&gt;
            generate_particles(particle_count)&lt;br /&gt;
            &lt;br /&gt;
        # Check if reset button was clicked&lt;br /&gt;
        if reset_button.clicked:&lt;br /&gt;
            #print(&amp;quot;reset clicked&amp;quot;)&lt;br /&gt;
            reset_button.clicked = False&lt;br /&gt;
            generate_particles(particle_count)&lt;br /&gt;
        if quit_button.clicked:&lt;br /&gt;
            break&lt;br /&gt;
    &lt;br /&gt;
        # Convert to grayscale and apply background subtraction&lt;br /&gt;
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)&lt;br /&gt;
        fgMask = backSub.apply(gray)&lt;br /&gt;
    &lt;br /&gt;
        # Find contours in the motion mask&lt;br /&gt;
        contours, _ = cv2.findContours(fgMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)&lt;br /&gt;
    &lt;br /&gt;
        motion_objects = []  # Reset motion objects each frame&lt;br /&gt;
    &lt;br /&gt;
        for cnt in contours:&lt;br /&gt;
            if cv2.contourArea(cnt) &amp;gt; min_area and len(motion_objects) &amp;lt; MAX_MOTION_OBJECTS:&lt;br /&gt;
                # Get bounding rectangle&lt;br /&gt;
                x, y, w, h = cv2.boundingRect(cnt)&lt;br /&gt;
    &lt;br /&gt;
                # Calculate center of motion&lt;br /&gt;
                center_x = x + w // 2&lt;br /&gt;
                center_y = y + h // 2&lt;br /&gt;
    &lt;br /&gt;
                # Calculate direction from center to motion area&lt;br /&gt;
                frame_center_x = frame.shape[1] // 2&lt;br /&gt;
                frame_center_y = frame.shape[0] // 2&lt;br /&gt;
    &lt;br /&gt;
                dx = center_x - frame_center_x&lt;br /&gt;
                dy = center_y - frame_center_y&lt;br /&gt;
    &lt;br /&gt;
                motion_objects.append((center_x, center_y, dx, dy))&lt;br /&gt;
                #cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)&lt;br /&gt;
                cv2.circle(frame, (center_x, center_y), 20, (255, 0, 255), -1)&lt;br /&gt;
                starsize=20&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x+starsize, center_y+starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x-starsize, center_y+starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x+starsize, center_y-starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x-starsize, center_y-starsize), (0, 255, 0), 2)&lt;br /&gt;
    &lt;br /&gt;
        # Update and draw particles&lt;br /&gt;
        update_particles(motion_objects)&lt;br /&gt;
        for particle in particles:&lt;br /&gt;
            x, y, _, _ = particle&lt;br /&gt;
            cv2.circle(frame, (int(x), int(y)), particle_size, particle_color, -1)&lt;br /&gt;
        for button in buttons:&lt;br /&gt;
            cv2.rectangle(frame, (button.x, button.y), (button.width, button.height), (255, 255, 255), -1)&lt;br /&gt;
            cv2.putText(frame, button.title, (button.x + 10, button.y + button.height - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2)&lt;br /&gt;
&lt;br /&gt;
        # Display the frame&lt;br /&gt;
        cv2.imshow(activityWindowName, frame)&lt;br /&gt;
    &lt;br /&gt;
        # Exit on &#039;q&#039; key&lt;br /&gt;
        if cv2.waitKey(30) &amp;amp; 0xFF == ord(&#039;q&#039;):&lt;br /&gt;
            break&lt;br /&gt;
    &lt;br /&gt;
    # Release resources&lt;br /&gt;
    cap.release()&lt;br /&gt;
    cv2.destroyAllWindows()&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Get available cameras&lt;br /&gt;
    #cameras = get_available_cameras&lt;br /&gt;
    cameras = enumerate_cameras()&lt;br /&gt;
    if not cameras:&lt;br /&gt;
        #print(&amp;quot;No cameras found!&amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
    if 0 == len(cameras):&lt;br /&gt;
        #print(&amp;quot;No cameras found!&amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Display stills and get user selection&lt;br /&gt;
    selected_camera = display_cameras_and_get_selection(cameras)&lt;br /&gt;
    # print(f&amp;quot;selected_camera:{selected_camera}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if selected_camera is not None:&lt;br /&gt;
        #print(f&amp;quot;Starting activity with selected camera: {selected_camera}&amp;quot;)&lt;br /&gt;
        # You can now use this camera index for further processing&lt;br /&gt;
        camera = next((camera for camera in cameras if camera.index == selected_camera), None)&lt;br /&gt;
&lt;br /&gt;
        if camera:&lt;br /&gt;
            # print(f&amp;quot;Found camera: {camera.index}, {camera.backend}&amp;quot;)&lt;br /&gt;
            pass&lt;br /&gt;
        else:&lt;br /&gt;
            # print(&amp;quot;Camera not found&amp;quot;)&lt;br /&gt;
            pass&lt;br /&gt;
&lt;br /&gt;
        activity(camera)&lt;br /&gt;
    else:&lt;br /&gt;
        #print(&amp;quot;No camera selected or operation cancelled&amp;quot;)&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Python_ball_pits&amp;diff=2948</id>
		<title>Python ball pits</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Python_ball_pits&amp;diff=2948"/>
		<updated>2026-03-01T04:05:31Z</updated>

		<summary type="html">&lt;p&gt;Shawn: New page with code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;d enjoyed the interactive particles on a screen with a camera I&#039;ve seen at the Museum of Science and other places, and I&#039;ve wanted to program them for years, so as I started to learn Python I used Devstral LLM to jumpstart a program, then added features.&lt;br /&gt;
Here&#039;s the code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
from cv2_enumerate_cameras import enumerate_cameras&lt;br /&gt;
import cv2&lt;br /&gt;
import numpy as np&lt;br /&gt;
import random&lt;br /&gt;
from collections import deque&lt;br /&gt;
import time&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Todo&lt;br /&gt;
Display on frame notice if no cameras found.&lt;br /&gt;
Button for quitting.&lt;br /&gt;
Button for going back to camera selection.&lt;br /&gt;
Convert from global variables to parameters passed to functions.&lt;br /&gt;
Variable particle colors, size, mass&lt;br /&gt;
Sliders/dials for parameters&lt;br /&gt;
Smoothly add/reduce particles&lt;br /&gt;
KNOW THAT VARIABLES INSIDE A FUNCTION CAN BE ACCESSED BY ENCLOSED FUNCTIONS&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
# Global variables&lt;br /&gt;
particle_count = 80  # Initial number of particles&lt;br /&gt;
min_area = 500       # Minimum area to consider as motion&lt;br /&gt;
history = 10         # Number of frames for background subtraction&lt;br /&gt;
particles = deque(maxlen=particle_count)&lt;br /&gt;
particle_size = 10&lt;br /&gt;
particle_color = (250, 200, 50) &lt;br /&gt;
motion_objects = []  # List to store motion objects (center, direction)&lt;br /&gt;
damping = 0.9995&lt;br /&gt;
gravity = 0.09&lt;br /&gt;
MAX_MOTION_OBJECTS = 10&lt;br /&gt;
STATES = (&amp;quot;Camera selection&amp;quot;, &amp;quot;Activity&amp;quot;)&lt;br /&gt;
state = 0&lt;br /&gt;
window_size = {&amp;quot;width&amp;quot;:1024,&amp;quot;height&amp;quot;:768}&lt;br /&gt;
&lt;br /&gt;
def capture_still(camera):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Capture a still image from the specified camera on its backend&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    cap = cv2.VideoCapture(camera.index, camera.backend)&lt;br /&gt;
    time.sleep(0.6) # Wait for camera to open before getting snapshot; some short times cause error.&lt;br /&gt;
    #print(&amp;quot;Captured a still&amp;quot;)&lt;br /&gt;
    ret, frame = cap.read()&lt;br /&gt;
    cap.release()&lt;br /&gt;
    return frame&lt;br /&gt;
            &lt;br /&gt;
def display_cameras_and_get_selection(cameras):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Display stills from all cameras and let user select one&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # cameras is a list of CameraInfo objects with properties we&#039;ll use: CameraInfo.name and CameraInfo.index&lt;br /&gt;
    camera_ID = None&lt;br /&gt;
    camera_indices = [camera.index for camera in cameras]&lt;br /&gt;
    #print(f&amp;quot;debug: camera_indices:{camera_indices}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def on_mouse_event_camera_selection(event, x, y, flags, param):&lt;br /&gt;
        nonlocal camera_ID&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Click event during camera selection&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        if event == cv2.EVENT_LBUTTONDOWN:&lt;br /&gt;
            # Get the list of camera indices and their positions&lt;br /&gt;
            camera_indices, positions = param&lt;br /&gt;
            # Check which camera was clicked&lt;br /&gt;
            for i, (cx, cy, cw, ch) in enumerate(positions):&lt;br /&gt;
                if cx &amp;lt;= x &amp;lt;= cx + cw and cy &amp;lt;= y &amp;lt;= cy + ch:&lt;br /&gt;
                    camera_ID = camera_indices[i]&lt;br /&gt;
                    #print(f&amp;quot;on_mouse_event_camera_selection set camera_ID: {camera_ID}&amp;quot;)&lt;br /&gt;
                    return&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Capture stills from all cameras&lt;br /&gt;
    stills = []&lt;br /&gt;
    for camera in cameras:&lt;br /&gt;
        stills.append(capture_still(camera))&lt;br /&gt;
&lt;br /&gt;
    # Create a window to display all stills&lt;br /&gt;
    window_name = &amp;quot;Select Camera&amp;quot;&lt;br /&gt;
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)&lt;br /&gt;
    cv2.resizeWindow(window_name, window_size[&amp;quot;width&amp;quot;], window_size[&amp;quot;height&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
    # Calculate grid layout&lt;br /&gt;
    cols = 4&lt;br /&gt;
    rows = (len(stills) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
    # Prepare to store camera positions&lt;br /&gt;
    camera_positions = []&lt;br /&gt;
&lt;br /&gt;
    # Calculate image size and spacing&lt;br /&gt;
    spacing = 10&lt;br /&gt;
    img_width = (window_size[&amp;quot;width&amp;quot;] - 2*spacing)//cols&lt;br /&gt;
    img_height = img_width * window_size[&amp;quot;height&amp;quot;] // window_size[&amp;quot;width&amp;quot;]&lt;br /&gt;
    #print(img_width, &amp;quot; &amp;quot;, img_height)&lt;br /&gt;
&lt;br /&gt;
    # Create a blank canvas of 1024x768&lt;br /&gt;
    canvas = np.ones((window_size[&amp;quot;height&amp;quot;], window_size[&amp;quot;width&amp;quot;], 3), dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
    # Display all stills in a grid on the canvas&lt;br /&gt;
    for i, still in enumerate(stills):&lt;br /&gt;
        row = i // cols&lt;br /&gt;
        col = i % cols&lt;br /&gt;
&lt;br /&gt;
        # Resize image to 320x240&lt;br /&gt;
        #print(f&amp;quot;Resizing: img_width, img_height:{img_width}, {img_height}&amp;quot;)&lt;br /&gt;
        resized = cv2.resize(still, (img_width, img_height))&lt;br /&gt;
&lt;br /&gt;
        # Calculate position in the grid&lt;br /&gt;
        x = col * (img_width + spacing)&lt;br /&gt;
        y = row * (img_height + spacing)&lt;br /&gt;
&lt;br /&gt;
        # Store camera position for click detection&lt;br /&gt;
        camera_positions.append((x, y, img_width, img_height))&lt;br /&gt;
&lt;br /&gt;
        # Place image on canvas&lt;br /&gt;
        canvas[y:y+img_height, x:x+img_width] = resized&lt;br /&gt;
&lt;br /&gt;
        # Add camera index text&lt;br /&gt;
        cv2.putText(canvas, f&amp;quot;Camera {camera_indices[i]}&amp;quot;, (x+10, y+20),&lt;br /&gt;
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)&lt;br /&gt;
&lt;br /&gt;
    # Display the canvas&lt;br /&gt;
    cv2.imshow(window_name, canvas)&lt;br /&gt;
&lt;br /&gt;
    # Set mouse callback&lt;br /&gt;
    cv2.setMouseCallback(window_name, on_mouse_event_camera_selection, (camera_indices, camera_positions))&lt;br /&gt;
&lt;br /&gt;
    # Wait for user to click on an image&lt;br /&gt;
    last_time=time.time()&lt;br /&gt;
    while True:&lt;br /&gt;
        key = cv2.waitKey(1) &amp;amp; 0xFF&lt;br /&gt;
        if time.time()-last_time &amp;gt; 1.0:&lt;br /&gt;
            last_time = time.time()&lt;br /&gt;
        if key == 27:  # ESC key to exit&lt;br /&gt;
            cv2.destroyAllWindows()&lt;br /&gt;
            return None&lt;br /&gt;
        if camera_ID is not None:&lt;br /&gt;
            cv2.destroyAllWindows()&lt;br /&gt;
            return camera_ID&lt;br /&gt;
&lt;br /&gt;
def activity(camera):    &lt;br /&gt;
    global particle_count&lt;br /&gt;
    global particles&lt;br /&gt;
    class button:&lt;br /&gt;
        def __init__(self, x, y, width, height, title):&lt;br /&gt;
            self.x = x&lt;br /&gt;
            self.y = y&lt;br /&gt;
            self.width = width&lt;br /&gt;
            self.height = height&lt;br /&gt;
            self.title = title&lt;br /&gt;
            self.clicked = False&lt;br /&gt;
        &lt;br /&gt;
    reset_button = button(10,10,100,40,&amp;quot;RESET&amp;quot;)&lt;br /&gt;
    quit_button = button(120,10,100,40,&amp;quot;QUIT&amp;quot;)&lt;br /&gt;
    buttons = [reset_button, quit_button]&lt;br /&gt;
    &lt;br /&gt;
    def on_mouse_click(event, x, y, flags, param):&lt;br /&gt;
        buttons = param&lt;br /&gt;
        if event == cv2.EVENT_LBUTTONDOWN:&lt;br /&gt;
            #print(&amp;quot;mouse clicked&amp;quot;)&lt;br /&gt;
            # Check if click is within the reset button area&lt;br /&gt;
            for button in buttons:&lt;br /&gt;
                if button.x &amp;lt;= x &amp;lt;= button.x+button.width and button.y &amp;lt;= y &amp;lt;= button.y+button.width:&lt;br /&gt;
                #print(&amp;quot;reset clicked&amp;quot;)&lt;br /&gt;
                    button.clicked = True&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def on_particle_count_change(val):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Callback function for particle count trackbar&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particle_count&lt;br /&gt;
        particle_count = val&lt;br /&gt;
    def update_particles(motion_objects):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Update particle positions and accelerate near motion objects&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particles&lt;br /&gt;
&lt;br /&gt;
        for i in range(len(particles)):&lt;br /&gt;
            x, y, dx, dy = particles[i]&lt;br /&gt;
            # Damp motion, more for faster particles&lt;br /&gt;
            dx *= damping/(1+(np.abs(dx)/1000))&lt;br /&gt;
            dy *= damping/(1+(np.abs(dy)/1000))&lt;br /&gt;
            dy += gravity&lt;br /&gt;
    &lt;br /&gt;
            # Check proximity to motion objects&lt;br /&gt;
            for obj in motion_objects:&lt;br /&gt;
                obj_x, obj_y, obj_dx, obj_dy = obj&lt;br /&gt;
                distance = np.sqrt((x - obj_x)**2 + (y - obj_y)**2)&lt;br /&gt;
    &lt;br /&gt;
                # If particle is near a motion object, accelerate in that direction&lt;br /&gt;
                if distance &amp;lt; 100:  # Proximity threshold&lt;br /&gt;
                    # Add motion vector to particle velocity&lt;br /&gt;
                    dx += obj_dx * 1/(distance+2)&lt;br /&gt;
                    dy += obj_dy * 1/(distance+2)&lt;br /&gt;
    &lt;br /&gt;
            # Update position&lt;br /&gt;
            x += dx&lt;br /&gt;
            y += dy&lt;br /&gt;
    &lt;br /&gt;
            # Bounce off edges&lt;br /&gt;
            frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)&lt;br /&gt;
            frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)&lt;br /&gt;
    &lt;br /&gt;
            if x &amp;lt;= 0:&lt;br /&gt;
                dx = np.abs(dx)&lt;br /&gt;
                x=0&lt;br /&gt;
            if x &amp;gt;= frame_width:&lt;br /&gt;
                dx = -1 * np.abs(dx)&lt;br /&gt;
                x = frame_width&lt;br /&gt;
            if y &amp;lt;= 0:&lt;br /&gt;
                dy = np.abs(dy)&lt;br /&gt;
                y=0&lt;br /&gt;
            if y &amp;gt;= frame_height:&lt;br /&gt;
                dy = -1 * np.abs(dy)&lt;br /&gt;
                y = frame_height&lt;br /&gt;
    &lt;br /&gt;
            particles[i] = [x, y, dx, dy]&lt;br /&gt;
&lt;br /&gt;
    def generate_particles(count=particle_count):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Generate particles at random positions&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        global particles&lt;br /&gt;
        nonlocal cap&lt;br /&gt;
        particles.clear()&lt;br /&gt;
        frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)&lt;br /&gt;
        frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)&lt;br /&gt;
    &lt;br /&gt;
        for _ in range(count):&lt;br /&gt;
            x = random.randint(0, int(frame_width))&lt;br /&gt;
            y = random.randint(0, int(frame_height))&lt;br /&gt;
            dx = random.uniform(-1, 1)  # Random initial velocity&lt;br /&gt;
            dy = random.uniform(-1, 1)&lt;br /&gt;
            particles.append([x, y, dx, dy])&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    # Initialize video capture with selected camera&lt;br /&gt;
    try:&lt;br /&gt;
        cap = cv2.VideoCapture(camera.index, camera.backend)&lt;br /&gt;
        if not cap.isOpened():&lt;br /&gt;
            pass&lt;br /&gt;
            #print(f&amp;quot;camera {camera_index} not available anymore.&amp;quot;)&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        pass&lt;br /&gt;
        #print(f&amp;quot;camera {camera_index} not available anymore. error {ValueError}&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    # Create window and trackbar&lt;br /&gt;
    activityWindowName=&#039;Motion Detection with Particles&#039;&lt;br /&gt;
    cv2.namedWindow(activityWindowName)&lt;br /&gt;
    cv2.createTrackbar(&#039;Particles&#039;, activityWindowName, particle_count, 100, on_particle_count_change)&lt;br /&gt;
    &lt;br /&gt;
    # Initialize background subtractor&lt;br /&gt;
    backSub = cv2.createBackgroundSubtractorMOG2(history, 16, True)&lt;br /&gt;
    &lt;br /&gt;
    # Generate initial particles&lt;br /&gt;
    generate_particles()&lt;br /&gt;
    cv2.setMouseCallback(activityWindowName, on_mouse_click, buttons)&lt;br /&gt;
&lt;br /&gt;
    while True:&lt;br /&gt;
        ret, frame = cap.read()&lt;br /&gt;
        if not ret:&lt;br /&gt;
            continue&lt;br /&gt;
    &lt;br /&gt;
        # Flip the frame horizontally&lt;br /&gt;
        frame = cv2.flip(frame, 1)&lt;br /&gt;
    &lt;br /&gt;
        # Get current particle count from trackbar&lt;br /&gt;
        current_particle_count = cv2.getTrackbarPos(&#039;Particles&#039;, activityWindowName)&lt;br /&gt;
        if current_particle_count != particle_count:&lt;br /&gt;
            particle_count = current_particle_count&lt;br /&gt;
            particles = deque(maxlen=particle_count)&lt;br /&gt;
            generate_particles(particle_count)&lt;br /&gt;
            &lt;br /&gt;
        # Check if reset button was clicked&lt;br /&gt;
        if reset_button.clicked:&lt;br /&gt;
            #print(&amp;quot;reset clicked&amp;quot;)&lt;br /&gt;
            reset_button.clicked = False&lt;br /&gt;
            generate_particles(particle_count)&lt;br /&gt;
        if quit_button.clicked:&lt;br /&gt;
            break&lt;br /&gt;
    &lt;br /&gt;
        # Convert to grayscale and apply background subtraction&lt;br /&gt;
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)&lt;br /&gt;
        fgMask = backSub.apply(gray)&lt;br /&gt;
    &lt;br /&gt;
        # Find contours in the motion mask&lt;br /&gt;
        contours, _ = cv2.findContours(fgMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)&lt;br /&gt;
    &lt;br /&gt;
        motion_objects = []  # Reset motion objects each frame&lt;br /&gt;
    &lt;br /&gt;
        for cnt in contours:&lt;br /&gt;
            if cv2.contourArea(cnt) &amp;gt; min_area and len(motion_objects) &amp;lt; MAX_MOTION_OBJECTS:&lt;br /&gt;
                # Get bounding rectangle&lt;br /&gt;
                x, y, w, h = cv2.boundingRect(cnt)&lt;br /&gt;
    &lt;br /&gt;
                # Calculate center of motion&lt;br /&gt;
                center_x = x + w // 2&lt;br /&gt;
                center_y = y + h // 2&lt;br /&gt;
    &lt;br /&gt;
                # Calculate direction from center to motion area&lt;br /&gt;
                frame_center_x = frame.shape[1] // 2&lt;br /&gt;
                frame_center_y = frame.shape[0] // 2&lt;br /&gt;
    &lt;br /&gt;
                dx = center_x - frame_center_x&lt;br /&gt;
                dy = center_y - frame_center_y&lt;br /&gt;
    &lt;br /&gt;
                motion_objects.append((center_x, center_y, dx, dy))&lt;br /&gt;
                #cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)&lt;br /&gt;
                cv2.circle(frame, (center_x, center_y), 20, (255, 0, 255), -1)&lt;br /&gt;
                starsize=20&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x+starsize, center_y+starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x-starsize, center_y+starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x+starsize, center_y-starsize), (0, 255, 0), 2)&lt;br /&gt;
                cv2.line(frame, (center_x, center_y), (center_x-starsize, center_y-starsize), (0, 255, 0), 2)&lt;br /&gt;
    &lt;br /&gt;
        # Update and draw particles&lt;br /&gt;
        update_particles(motion_objects)&lt;br /&gt;
        for particle in particles:&lt;br /&gt;
            x, y, _, _ = particle&lt;br /&gt;
            cv2.circle(frame, (int(x), int(y)), particle_size, particle_color, -1)&lt;br /&gt;
        for button in buttons:&lt;br /&gt;
            cv2.rectangle(frame, (button.x, button.y), (button.width, button.height), (255, 255, 255), -1)&lt;br /&gt;
            cv2.putText(frame, button.title, (button.x + 10, button.y + button.height - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2)&lt;br /&gt;
&lt;br /&gt;
        # Display the frame&lt;br /&gt;
        cv2.imshow(activityWindowName, frame)&lt;br /&gt;
    &lt;br /&gt;
        # Exit on &#039;q&#039; key&lt;br /&gt;
        if cv2.waitKey(30) &amp;amp; 0xFF == ord(&#039;q&#039;):&lt;br /&gt;
            break&lt;br /&gt;
    &lt;br /&gt;
    # Release resources&lt;br /&gt;
    cap.release()&lt;br /&gt;
    cv2.destroyAllWindows()&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Get available cameras&lt;br /&gt;
    #cameras = get_available_cameras&lt;br /&gt;
    cameras = enumerate_cameras()&lt;br /&gt;
    if not cameras:&lt;br /&gt;
        #print(&amp;quot;No cameras found!&amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
    if 0 == len(cameras):&lt;br /&gt;
        #print(&amp;quot;No cameras found!&amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Display stills and get user selection&lt;br /&gt;
    selected_camera = display_cameras_and_get_selection(cameras)&lt;br /&gt;
    # print(f&amp;quot;selected_camera:{selected_camera}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if selected_camera is not None:&lt;br /&gt;
        #print(f&amp;quot;Starting activity with selected camera: {selected_camera}&amp;quot;)&lt;br /&gt;
        # You can now use this camera index for further processing&lt;br /&gt;
        camera = next((camera for camera in cameras if camera.index == selected_camera), None)&lt;br /&gt;
&lt;br /&gt;
        if camera:&lt;br /&gt;
            # print(f&amp;quot;Found camera: {camera.index}, {camera.backend}&amp;quot;)&lt;br /&gt;
            pass&lt;br /&gt;
        else:&lt;br /&gt;
            # print(&amp;quot;Camera not found&amp;quot;)&lt;br /&gt;
            pass&lt;br /&gt;
&lt;br /&gt;
        activity(camera)&lt;br /&gt;
    else:&lt;br /&gt;
        #print(&amp;quot;No camera selected or operation cancelled&amp;quot;)&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2947</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2947"/>
		<updated>2025-04-26T00:44:17Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Program */ interrupts and precision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates.&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate: Minimum 16x2 LCD.&lt;br /&gt;
*Power by battery or USB.&lt;br /&gt;
**Option: Power by rechargeable battery.&lt;br /&gt;
**Option: Include a power switch to save the battery.&lt;br /&gt;
*Expose reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s or better.&lt;br /&gt;
**Option: Time entry and exit at each gate to get local speed.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. There are many to choose from:&lt;br /&gt;
**I first used a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Since the 2010s, I have used a breadboard Microchip/Atmel 328P. You can easily program this with the Arduino system.&lt;br /&gt;
**In the 2020s, I use Adafruit Feather. These are breadboard-friendly devices that include a battery-charger and many options for micro-controllers, like RP2040, ESP32, and Atmel 32u4. Some even have built-in displays.&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**TFT display. These are bright displays, easier to read in dark situations, but use more power than LCDs.&lt;br /&gt;
**7-segment display. You can use a 4-digit 7-segment display to display milliseconds or centiseconds&lt;br /&gt;
*Could use a computer connection to enter data directly into a spreadsheet:&lt;br /&gt;
**A TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
**USB-HID-capable microcontroller boards like Adafruit&#039;s RP2040 Key Boar ($10), Arduino Leonardo, etc.&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
**5V adapter from 2000s era phones.&lt;br /&gt;
**5V USB charger.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
Micro-controllers can be programmed in higher level languages like MicroPython and CircuitPython, a little &amp;quot;closer to the metal&amp;quot; with Arduino, or in the language built into the hardware. It is important to consider the difference in precision available according to the range of time the program takes to respond to the external signals from the photo-gates. It is best to use &amp;quot;hardware interrupts,&amp;quot; available in only some programming environments.&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD, 1.5mm pitch, spread to fit onto a 0.1&amp;quot; (2.54mm) pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. https://doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2946</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2946"/>
		<updated>2025-04-23T17:04:43Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates.&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate: Minimum 16x2 LCD.&lt;br /&gt;
*Power by battery or USB.&lt;br /&gt;
**Option: Power by rechargeable battery.&lt;br /&gt;
**Option: Include a power switch to save the battery.&lt;br /&gt;
*Expose reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s or better.&lt;br /&gt;
**Option: Time entry and exit at each gate to get local speed.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. There are many to choose from:&lt;br /&gt;
**I first used a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Since the 2010s, I have used a breadboard Microchip/Atmel 328P. You can easily program this with the Arduino system.&lt;br /&gt;
**In the 2020s, I use Adafruit Feather. These are breadboard-friendly devices that include a battery-charger and many options for micro-controllers, like RP2040, ESP32, and Atmel 32u4. Some even have built-in displays.&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**TFT display. These are bright displays, easier to read in dark situations, but use more power than LCDs.&lt;br /&gt;
**7-segment display. You can use a 4-digit 7-segment display to display milliseconds or centiseconds&lt;br /&gt;
*Could use a computer connection to enter data directly into a spreadsheet:&lt;br /&gt;
**A TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
**USB-HID-capable microcontroller boards like Adafruit&#039;s RP2040 Key Boar ($10), Arduino Leonardo, etc.&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
**5V adapter from 2000s era phones.&lt;br /&gt;
**5V USB charger.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD, 1.5mm pitch, spread to fit onto a 0.1&amp;quot; (2.54mm) pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. https://doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2945</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2945"/>
		<updated>2025-04-23T16:38:39Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Specifications */ Power and speed options&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates.&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate: Minimum 16x2 LCD.&lt;br /&gt;
*Power by battery or USB.&lt;br /&gt;
**Option: Power by rechargeable battery.&lt;br /&gt;
**Option: Include a power switch to save the battery.&lt;br /&gt;
*Expose reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s or better.&lt;br /&gt;
**Option: Time entry and exit at each gate to get local speed.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. There are many to choose from:&lt;br /&gt;
**I first used a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Since the 2010s, I have used a breadboard Microchip/Atmel 328P. You can easily program this with the Arduino system.&lt;br /&gt;
**In the 2020s, I use Adafruit Feather. These are breadboard-friendly devices that include a battery-charger and many options for micro-controllers, like RP2040, ESP32, and Atmel 32u4. Some even have built-in displays.&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**TFT display. These are bright displays, easier to read in dark situations, but use more power than LCDs.&lt;br /&gt;
**7-segment display. You can use a 4-digit 7-segment display to display milliseconds or centiseconds&lt;br /&gt;
*Could use a computer connection to enter data directly into a spreadsheet:&lt;br /&gt;
**A TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
**USB-HID-capable microcontroller boards like Adafruit&#039;s RP2040 Key Boar ($10), Arduino Leonardo, etc.&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
**5V adapter from 2000s era phones.&lt;br /&gt;
**5V USB charger.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD, 1.5mm pitch, spread to fit onto a 0.1&amp;quot; (2.54mm) pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2944</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2944"/>
		<updated>2025-04-21T13:36:01Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photogate Timer ESP32.jpeg|300px|thumbnail|right|ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.]]&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module, so outputting text requires only the built-in print() function.&lt;br /&gt;
&lt;br /&gt;
== Codes ==&lt;br /&gt;
===Timer===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#pull is whether you use internal pullup/pulldown. False if you use an external switch.&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===Speeds===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate interval meter&amp;quot;)&lt;br /&gt;
#Dialog to enter length of device, through matrix keyboard, in mm?&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty dictionaries, keys will be key_number:&lt;br /&gt;
startTimes = {}&lt;br /&gt;
endTimes = {}&lt;br /&gt;
speeds = {}&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #debug&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #Enter gate: event.pressed==True&lt;br /&gt;
        #Exit gate: event.pressed==False&lt;br /&gt;
        #if object is entering a gate:&lt;br /&gt;
        if event.pressed==True:&lt;br /&gt;
            startTimes[event.key_number] = time.monotonic()&lt;br /&gt;
        elif event.pressed==False:&lt;br /&gt;
            endTimes[event.key_number] = time.monotonic()&lt;br /&gt;
            if startTimes[event.key_number]&amp;gt;0.00:&lt;br /&gt;
                print(event.key_number, endTimes[event.key_number]-startTimes[event.key_number])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2943</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2943"/>
		<updated>2025-04-20T18:43:22Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Datasheets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. There are many to choose from:&lt;br /&gt;
**I first used a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Since the 2010s, I have used a breadboard Microchip/Atmel 328P. You can easily program this with the Arduino system.&lt;br /&gt;
**In the 2020s, I use Adafruit Feather. These are breadboard-friendly devices that include a battery-charger and many options for micro-controllers, like RP2040, ESP32, and Atmel 32u4. Some even have built-in displays.&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**TFT display. These are bright displays, easier to read in dark situations, but use more power than LCDs.&lt;br /&gt;
**7-segment display. You can use a 4-digit 7-segment display to display milliseconds or centiseconds&lt;br /&gt;
*Could use a computer connection to enter data directly into a spreadsheet:&lt;br /&gt;
**A TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
**USB-HID-capable microcontroller boards like Adafruit&#039;s RP2040 Key Boar ($10), Arduino Leonardo, etc.&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
**5V adapter from 2000s era phones.&lt;br /&gt;
**5V USB charger.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD, 1.5mm pitch, spread to fit onto a 0.1&amp;quot; (2.54mm) pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2942</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2942"/>
		<updated>2025-04-20T18:38:59Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Components */ Expanding possibilities&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. There are many to choose from:&lt;br /&gt;
**I first used a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Since the 2010s, I have used a breadboard Microchip/Atmel 328P. You can easily program this with the Arduino system.&lt;br /&gt;
**In the 2020s, I use Adafruit Feather. These are breadboard-friendly devices that include a battery-charger and many options for micro-controllers, like RP2040, ESP32, and Atmel 32u4. Some even have built-in displays.&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**TFT display. These are bright displays, easier to read in dark situations, but use more power than LCDs.&lt;br /&gt;
**7-segment display. You can use a 4-digit 7-segment display to display milliseconds or centiseconds&lt;br /&gt;
*Could use a computer connection to enter data directly into a spreadsheet:&lt;br /&gt;
**A TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
**USB-HID-capable microcontroller boards like Adafruit&#039;s RP2040 Key Boar ($10), Arduino Leonardo, etc.&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
**5V adapter from 2000s era phones.&lt;br /&gt;
**5V USB charger.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2941</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2941"/>
		<updated>2025-04-20T17:36:10Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Datasheets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller: https://www.microchip.com/en-us/product/atmega328p&lt;br /&gt;
;PICAXE micro-controller system for education: https://picaxe.com/software/&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2940</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2940"/>
		<updated>2025-04-20T17:35:13Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Datasheets */ updated links to Lite-on semiconductors.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller:http://www.atmel.com/devices/ATMEGA328P.aspx&lt;br /&gt;
;PICAXE micro-controller system for education:http://picaxe.com&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter: https://optoelectronics.liteon.com/upload/download/DS-50-92-0009/E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor: https://optoelectronics.liteon.com/upload/download/DS-50-93-0013/LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2939</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2939"/>
		<updated>2025-04-02T17:14:45Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photogate Timer ESP32.jpeg|300px|thumbnail|right|ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.]]&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module, so outputting text requires only the built-in print() function.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#pull is whether you use internal pullup/pulldown. False if you use an external switch.&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2938</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2938"/>
		<updated>2025-04-02T17:13:02Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* ESP32-S2 Reverse TFT Feather */ reference to print() function.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photogate Timer ESP32.jpeg|300px|thumbnail|right|ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.]]&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module, so outputting text requires only the built-in print() function.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2937</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2937"/>
		<updated>2025-04-02T17:10:45Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photogate Timer ESP32.jpeg|300px|thumbnail|right|ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.]]&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2936</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2936"/>
		<updated>2025-04-02T17:09:50Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* ESP32-S2 Reverse TFT Feather */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
[[File:Photogate Timer ESP32.jpeg|300px|thumbnail|right|ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.]]&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=File:Photogate_Timer_ESP32.jpeg&amp;diff=2935</id>
		<title>File:Photogate Timer ESP32.jpeg</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=File:Photogate_Timer_ESP32.jpeg&amp;diff=2935"/>
		<updated>2025-04-02T17:08:34Z</updated>

		<summary type="html">&lt;p&gt;Shawn: ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
ESP32 with reverse TFT display running Circuit Python, showing REPL output, the last two lines being the mark of the first button pressed beginning timing, and then the updated list of times when the second button pressed.&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2934</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2934"/>
		<updated>2025-03-31T02:34:53Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* CircuitPython */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
[https://circuitpython.org CircuitPython] is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2933</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2933"/>
		<updated>2025-03-31T02:29:11Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* ESP32-S2 Reverse TFT Feather */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable radio.&lt;br /&gt;
&lt;br /&gt;
The same text output to the Python REPL on the computer is output to the screen on the module.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2932</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2932"/>
		<updated>2025-03-31T02:25:54Z</updated>

		<summary type="html">&lt;p&gt;Shawn: link to parent article.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&lt;br /&gt;
== CircuitPython ==&lt;br /&gt;
CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_a_PICAXE_20M2&amp;diff=2931</id>
		<title>Photo-gate timer with a PICAXE 20M2</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_a_PICAXE_20M2&amp;diff=2931"/>
		<updated>2025-03-31T02:25:20Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Program listing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Program listing===&lt;br /&gt;
This program can be compiled for a PICAXE 20M2, paired with a Newhaven 3V i2c LCD display. It will watch for high signals on five input pins, starting with C.5, and display times between C.5 tripping and the rest of the gates.&lt;br /&gt;
&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;BASIC&amp;quot; line copy&amp;gt;&lt;br /&gt;
 ;2014 Shawn Reeves&lt;br /&gt;
 ;Hardware notes:&lt;br /&gt;
 ;only C.1 to C.5 may be used as interrupts on the 20M2 or 20X2 parts&lt;br /&gt;
 ;Only 20X2 and greater parts offer a dedicated hardware timer. To use 20M2, we use software counting&lt;br /&gt;
 ;Tested with a 20M2 to 20ms precision, but may drift with temperature, ICs, VCC.&lt;br /&gt;
 ;For more precise timing, leave the PICAXE environment for a crystal-timed µC with hardware timer.&lt;br /&gt;
 ;Attach a photo-gate to pins 5, 6 (and optionally 7, 8, then 9) of the PICAXE 20M2&lt;br /&gt;
 ;Tie unused photo-gate pins to ground or spurious signals will trip floating pins.&lt;br /&gt;
 ;Gates should provide TTL output &lt;br /&gt;
 ;LCD display contrast depends on voltage of power supplied.&lt;br /&gt;
 ; Here it is adjusted to be readable from 3.3V to to 2.9V. Lower voltage will make lighter characters.&lt;br /&gt;
 &lt;br /&gt;
 #picaxe 20M2	;declare type so compiler works correctly.&lt;br /&gt;
 symbol count1 = w1	;track the time at second gate (pin 6)&lt;br /&gt;
 symbol count2 = w2	;track the time at third gate&lt;br /&gt;
 symbol count3 = w3	;track the time at fourth gate&lt;br /&gt;
 symbol count4 = w4	;track the time at fifth gate&lt;br /&gt;
 symbol counter = w5	;track the time since first gate was crossed (pin 5)&lt;br /&gt;
 symbol loopWord = w6&lt;br /&gt;
 symbol ones = b14&lt;br /&gt;
 symbol tens = b15&lt;br /&gt;
 symbol hundreds = b16&lt;br /&gt;
 symbol thousands = b17&lt;br /&gt;
 symbol tenThousands = b18&lt;br /&gt;
 &lt;br /&gt;
 symbol interruptPin = b1 	;Track which gate we expect to close next&lt;br /&gt;
 symbol LCDAddress = 124	;0x7C&lt;br /&gt;
 symbol controlByte = 0&lt;br /&gt;
 symbol functionSetDisplay = 0x38&lt;br /&gt;
 symbol clearDisplay = 1&lt;br /&gt;
 symbol homeDisplay = 2&lt;br /&gt;
 symbol updatePeriod = 100	;How often to refresh display, in centiseconds. The larger, the more precise the timing&lt;br /&gt;
 &lt;br /&gt;
 init:&lt;br /&gt;
 pause 1000	;give a second for inputs to settle&lt;br /&gt;
 ;setfreq will affect all future timing instructions, including pause, pauseus, and hi2csetup&lt;br /&gt;
 setfreq m32&lt;br /&gt;
 ;HI2CSETUP I2CMASTER, slaveaddress, i2cfast | i2cslow | i2cfast_8 | i2cslow_8 | i2cfast_16 | etc, i2cbyte | i2cword&lt;br /&gt;
 HI2CSETUP I2CMASTER, LCDAddress, i2cfast_32, i2cbyte&lt;br /&gt;
 initLCD:&lt;br /&gt;
 hi2cout 0,($38);%00111000; FUNCTION SET 8 bit, 2 line, not double-height, 0, instruction set zero&lt;br /&gt;
 pause 2&lt;br /&gt;
 hi2cout 0,($39);%00111001; FUNCTION SET 8 bit, 2 line, not double-height, 0, instruction set one&lt;br /&gt;
 pause 2&lt;br /&gt;
 hi2cout 0,($14);%00010100; OSC set 1/5 bias, frequency last three bits&lt;br /&gt;
 hi2cout 0,(%01111111);%01111000; Contrast set, four least significant contrast bits&lt;br /&gt;
 hi2cout 0,(%01011101);%01011110; Power/ICON set, Icon on, booster on, two most significant contrast bits&lt;br /&gt;
 hi2cout 0,($6D);%01101101; FOLLOWER CONTROL, follower on, last three bits follower amp ratio&lt;br /&gt;
 hi2cout 0,($38);BACK TO INSTRUCTION SET ZERO&lt;br /&gt;
 hi2cout 0,($0C);%00001100; DISPLAY ON, display on, cursor off, cursor position off&lt;br /&gt;
 hi2cout 0,($01)		; Clear display&lt;br /&gt;
 hi2cout 0,($06);%00000110;	ENTRY MODE, increment cursor, don&#039;t shift display&lt;br /&gt;
 pause 3&lt;br /&gt;
 &lt;br /&gt;
 restarting:&lt;br /&gt;
 hi2cout 0, ($80)	;set data address to beginning of line 1&lt;br /&gt;
 hi2cout $40, (&amp;quot;waiting for 1st gate&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 counter = 0&lt;br /&gt;
 count1 = 0&lt;br /&gt;
 count2 = 0&lt;br /&gt;
 count3 = 0&lt;br /&gt;
 count4 = 0&lt;br /&gt;
 interruptPin = 32	;%00100000	;Start at C.5&lt;br /&gt;
 ;set interrupt on inputs along port C, starting with C.5, C.4, ... for each photogate&lt;br /&gt;
 setint interruptPin,interruptPin	;Interrupt only on current expected pin&lt;br /&gt;
 &lt;br /&gt;
 main:&lt;br /&gt;
 ;Breaking 10µs pause into 1µs pauses, since interrupt causes program to go to next line&lt;br /&gt;
 ;;no matter how far pause was in execution.&lt;br /&gt;
 ;the timing overhead for each iteration of the following loop is about 40µs&lt;br /&gt;
 for loopWord = 2 to updatePeriod&lt;br /&gt;
 	pauseus 7700	;in units of 10µs (divided by frequency scale, 8), so this will count every 10 ms, our least significant digit&lt;br /&gt;
 	inc counter&lt;br /&gt;
 next loopWord&lt;br /&gt;
 pauseus 6000	;adjust down from 10ms to account for display routine below. since setfreq is 32, 8000 is 10ms.&lt;br /&gt;
 inc counter&lt;br /&gt;
 #ifdef calibrateTime&lt;br /&gt;
 	;the following conversion and display take about 2.5ms&lt;br /&gt;
 	BINTOASCII counter, tenThousands, thousands, hundreds, tens, ones	;display counter to calibrate timing&lt;br /&gt;
 	hi2cout 0, ($C8)	;set data address to middle of line 2&lt;br /&gt;
 	hi2cout $40, (tenThousands, thousands, hundreds, %00101110, tens, ones)&lt;br /&gt;
 #else&lt;br /&gt;
 	pauseus 1500;estimate of amount of overhead the above time display would take.&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 goto main&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 interrupt:&lt;br /&gt;
 if interruptPin = 32 then	;first gate was tripped, so start counting&lt;br /&gt;
 	counter = 0&lt;br /&gt;
 	count1 = 0&lt;br /&gt;
 	count2 = 0&lt;br /&gt;
 	count3 = 0&lt;br /&gt;
 	count4 = 0&lt;br /&gt;
 	interruptPin = 16&lt;br /&gt;
 	setint interruptPin,interruptPin	;Interrupt only on current expected pin&lt;br /&gt;
 	hi2cout 0, ($80)	;set data address to beginning of line 1&lt;br /&gt;
 	hi2cout $40, (&amp;quot;1st gate tripped&amp;quot;)&lt;br /&gt;
 else if interruptPin = 16 then	;next gate was tripped, get time&lt;br /&gt;
 	count1 = counter&lt;br /&gt;
 	interruptPin = 8&lt;br /&gt;
 	setint interruptPin,interruptPin	;Interrupt only on current expected pin&lt;br /&gt;
 	hi2cout 0, ($80)	;set data address to beginning of line 1&lt;br /&gt;
 	BINTOASCII count1, tenThousands, thousands, hundreds, tens, ones&lt;br /&gt;
 	hi2cout $40, (tenThousands, thousands, hundreds, %00101110, tens, ones,32,32,32,32,32,32,32,32,32,32);clear 1st line&lt;br /&gt;
 else if interruptPin = 8 then&lt;br /&gt;
 	count2 = counter&lt;br /&gt;
 	interruptPin = 4&lt;br /&gt;
 	setint interruptPin,interruptPin	;Interrupt only on current expected pin&lt;br /&gt;
 	hi2cout 0, ($88)	;set data address to middle of line 1&lt;br /&gt;
 	BINTOASCII count2, tenThousands, thousands, hundreds, tens, ones&lt;br /&gt;
 	hi2cout $40, (tenThousands, thousands, hundreds, %00101110, tens, ones,32,32)&lt;br /&gt;
 else if interruptPin = 4 then&lt;br /&gt;
 	count3 = counter&lt;br /&gt;
 	interruptPin = 2&lt;br /&gt;
 	setint interruptPin,interruptPin	;Interrupt only on current expected pin&lt;br /&gt;
 	hi2cout 0, ($C0)	;set data address to beginning of line 2&lt;br /&gt;
 	BINTOASCII count3, tenThousands, thousands, hundreds, tens, ones&lt;br /&gt;
 	hi2cout $40, (tenThousands, thousands, hundreds, %00101110, tens, ones)&lt;br /&gt;
 else if interruptPin = 2 then&lt;br /&gt;
 	count4 = counter&lt;br /&gt;
 	interruptPin = 32	;allow hitting the original to reset&lt;br /&gt;
 	hi2cout 0, ($C8)	;set data address to middle of line 2&lt;br /&gt;
 	BINTOASCII count4, tenThousands, thousands, hundreds, tens, ones&lt;br /&gt;
 	hi2cout $40, (tenThousands, thousands, hundreds, %00101110, tens, ones)&lt;br /&gt;
 endif&lt;br /&gt;
 &lt;br /&gt;
 return&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_an_Arduino&amp;diff=2930</id>
		<title>Photo-gate timer with an Arduino</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_an_Arduino&amp;diff=2930"/>
		<updated>2025-03-31T02:17:57Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Program listing */ syntax highlighting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Program listing===&lt;br /&gt;
This program can be compiled for an Atmel 328P, running at 2MHz (!), paired with a Newhaven 3V i2c LCD display. It will watch for low signals on five input pins.&lt;br /&gt;
&lt;br /&gt;
See [[Photo-gate timer]] for a full discussion.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line copy&amp;gt;&lt;br /&gt;
//By Shawn Reeves. 2014.&lt;br /&gt;
 //Compile in Arduino IDE. Requires PinChangeInt library that isn&#039;t part of standard install.&lt;br /&gt;
 /*On timing:&lt;br /&gt;
 micros() returns the number of microseconds since the Arduino board began running the current program.&lt;br /&gt;
 micros() returns an unsigned long integer, so it overflows to zero after 4,294,967,295 µs.&lt;br /&gt;
 millis() is similar except it counts milliseconds.&lt;br /&gt;
 NOTA BENE:Both millis() and micros() clear interrupts while they read the timer, so use them sparingly!&lt;br /&gt;
 */&lt;br /&gt;
 /*On interrupts:&lt;br /&gt;
 The Atmega 328 only has two fully independent hardware interrupts, but it has more grouped-pin interrupts.&lt;br /&gt;
 We use the PinChangeInt library to enable the PCINT on the Atmega328 ports.&lt;br /&gt;
 We&#039;ve programmed using switch...case so that the gates can be tripped in any order,&lt;br /&gt;
  but their position in the display goes by how they are hardwired.&lt;br /&gt;
 What if two interrupts happen simultaneously?&lt;br /&gt;
  If two interrupts happen withing microseconds of each other, we might be processing and displaying one&lt;br /&gt;
  and mixing up the values.&lt;br /&gt;
  So, we should have an array of hit_time variables for each gate.&lt;br /&gt;
  This way this can be used as a race-track timer without fear of complications.&lt;br /&gt;
 */&lt;br /&gt;
 #include &amp;lt;PinChangeInt.h&amp;gt;&lt;br /&gt;
 //Assign meaningful names to the pins&lt;br /&gt;
 /*Since we are going to cause interrupt on a change on every pin of an involved port,&lt;br /&gt;
 let&#039;s pick fewest number of ports. If there aren&#039;t five free pins on any port, then one for the first gate&lt;br /&gt;
 and another for the rest of the gates.&lt;br /&gt;
 If using i2c, avoid Port C, since it is partly used for i2c with display.&lt;br /&gt;
 If using SPI, avoid Port B.&lt;br /&gt;
 If using UART Serial, avoid Port D.&lt;br /&gt;
 */&lt;br /&gt;
 #define gate0 8   //328 pin 14&lt;br /&gt;
 #define gate1 2   //328 pin 4&lt;br /&gt;
 #define gate2 3   //328 pin 5&lt;br /&gt;
 #define gate3 10  //328 pin 16&lt;br /&gt;
 #define gate4 9   //328 pin 15&lt;br /&gt;
 /*On LCD display&lt;br /&gt;
 We are using an i2c LCD display from Newhaven Display.&lt;br /&gt;
 The Wire library sends i2c commands and data.&lt;br /&gt;
 */&lt;br /&gt;
 #include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
 #define LCD_address 0x3E  //0x7C shifted right one bit&lt;br /&gt;
 #define command_send 0  //prefix commands to the i2c LCD&lt;br /&gt;
 #define data_send 0x40&lt;br /&gt;
 #define line2_address 0xC0&lt;br /&gt;
 //Declare variables to track interrupt pins:&lt;br /&gt;
 volatile uint8_t latest_interrupted_pin = 255;//whenever it isn&#039;t 255 an interrupt has happened.&lt;br /&gt;
 volatile unsigned long hit_Time;&lt;br /&gt;
 unsigned long start_Time;&lt;br /&gt;
 unsigned long this_Time;&lt;br /&gt;
 byte first_hit;&lt;br /&gt;
 &lt;br /&gt;
 void setup() {&lt;br /&gt;
   delay(100);//Wait for display to power up.&lt;br /&gt;
   pinMode(gate0, INPUT_PULLUP);  //Enable internal pullup resistor--Photogate circuit will drive this input low.&lt;br /&gt;
   pinMode(gate1, INPUT_PULLUP);  //Enable internal pullup resistor--Photogate circuit will drive this input low.&lt;br /&gt;
   pinMode(gate2, INPUT_PULLUP);  //Enable internal pullup resistor--Photogate circuit will drive this input low.&lt;br /&gt;
   pinMode(gate3, INPUT_PULLUP);  //Enable internal pullup resistor--Photogate circuit will drive this input low.&lt;br /&gt;
   pinMode(gate4, INPUT_PULLUP);  //Enable internal pullup resistor--Photogate circuit will drive this input low.&lt;br /&gt;
   PCintPort::attachInterrupt(gate0, &amp;amp;interrupt_function, RISING);  //Watch the first gate.&lt;br /&gt;
   Wire.begin(); // join i2c bus (address optional for master)&lt;br /&gt;
   i2c_LCD_setup();&lt;br /&gt;
   i2c_LCD_display_waiting();&lt;br /&gt;
 }&lt;br /&gt;
 void loop() {&lt;br /&gt;
   switch (latest_interrupted_pin){&lt;br /&gt;
     case 255://no interrupt since last check&lt;br /&gt;
       break;&lt;br /&gt;
     case gate0:&lt;br /&gt;
       start_Time=hit_Time;&lt;br /&gt;
       i2c_LCD_display_tripped();&lt;br /&gt;
       first_hit=1;latest_interrupted_pin=255;&lt;br /&gt;
       PCintPort::attachInterrupt(gate1, &amp;amp;interrupt_function, RISING);&lt;br /&gt;
       PCintPort::attachInterrupt(gate2, &amp;amp;interrupt_function, RISING);&lt;br /&gt;
       PCintPort::attachInterrupt(gate3, &amp;amp;interrupt_function, RISING);&lt;br /&gt;
       PCintPort::attachInterrupt(gate4, &amp;amp;interrupt_function, RISING);&lt;br /&gt;
       break;&lt;br /&gt;
     case gate1:&lt;br /&gt;
       this_Time=hit_Time - start_Time;&lt;br /&gt;
       if (1==first_hit){&lt;br /&gt;
         clear_LCD(); first_hit=0;//this is the first gate tripped. Clear the waiting msg and reset our flag.&lt;br /&gt;
       }&lt;br /&gt;
       LCD_address_go(0);&lt;br /&gt;
       i2c_LCD_display_time();latest_interrupted_pin=255;&lt;br /&gt;
       break;&lt;br /&gt;
     case gate2:&lt;br /&gt;
       this_Time=hit_Time - start_Time;&lt;br /&gt;
       if (1==first_hit){&lt;br /&gt;
         clear_LCD(); first_hit=0;//this is the first gate tripped. Clear the waiting msg and reset our flag.&lt;br /&gt;
       }&lt;br /&gt;
       LCD_address_go(1);&lt;br /&gt;
       i2c_LCD_display_time();latest_interrupted_pin=255;&lt;br /&gt;
       break;&lt;br /&gt;
     case gate3:&lt;br /&gt;
       this_Time=hit_Time - start_Time;&lt;br /&gt;
       if (1==first_hit){&lt;br /&gt;
         clear_LCD(); first_hit=0;//this is the first gate tripped. Clear the waiting msg and reset our flag.&lt;br /&gt;
       }&lt;br /&gt;
       LCD_address_go(2);&lt;br /&gt;
       i2c_LCD_display_time();latest_interrupted_pin=255;&lt;br /&gt;
       break;&lt;br /&gt;
     case gate4:&lt;br /&gt;
       this_Time=hit_Time - start_Time;&lt;br /&gt;
       if (1==first_hit){&lt;br /&gt;
         clear_LCD(); first_hit=0;//this is the first gate tripped. Clear the waiting msg and reset our flag.&lt;br /&gt;
       }&lt;br /&gt;
       LCD_address_go(3);&lt;br /&gt;
       i2c_LCD_display_time();latest_interrupted_pin=255;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 void interrupt_function() {&lt;br /&gt;
   latest_interrupted_pin=PCintPort::arduinoPin;&lt;br /&gt;
   hit_Time = millis();&lt;br /&gt;
 }&lt;br /&gt;
 void i2c_LCD_display_tripped(){&lt;br /&gt;
   clear_LCD();&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(data_send);&lt;br /&gt;
   Wire.write(&amp;quot;1st gate tripped&amp;quot;);&lt;br /&gt;
   Wire.endTransmission();&lt;br /&gt;
 }&lt;br /&gt;
 void i2c_LCD_display_waiting(){&lt;br /&gt;
   clear_LCD();&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(data_send);&lt;br /&gt;
   Wire.write(&amp;quot;Waiting...&amp;quot;);&lt;br /&gt;
   Wire.endTransmission();&lt;br /&gt;
 }&lt;br /&gt;
 void i2c_LCD_display_time(){&lt;br /&gt;
   this_Time = this_Time * 8;//shift since we&#039;re using 2MHz instead of 16MHz standard arduino crystal.&lt;br /&gt;
   //The above shift makes the milliseconds digit insignificant. For millisecond precision, use a 16MHz system&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(data_send);&lt;br /&gt;
   this_Time = this_Time % 100000;  //Ensure value is less than 100000&lt;br /&gt;
   Wire.write(48 + (this_Time / 10000));  //Print the 10000 digit&lt;br /&gt;
   this_Time = this_Time % 10000;  //Get rid of the 10000 digit&lt;br /&gt;
   Wire.write(48 + (this_Time / 1000));  //Print the 1000 digit&lt;br /&gt;
   Wire.write(&amp;quot;.&amp;quot;);&lt;br /&gt;
   this_Time = this_Time % 1000;  //Get rid of the 1000 digit&lt;br /&gt;
   Wire.write(48 + (this_Time / 100));  //Print the 100 digit&lt;br /&gt;
   this_Time = this_Time % 100;  //Get rid of the 100 digit&lt;br /&gt;
   Wire.write(48 + (this_Time / 10));  //Print the 10 digit&lt;br /&gt;
   /* See discussion above about precision. Uncomment if using 16MHz or precise system.&lt;br /&gt;
   this_Time = this_Time % 10;  //Get rid of the 10 digit&lt;br /&gt;
   Wire.write(48 + this_Time);  //Print the 1 digit&lt;br /&gt;
   */&lt;br /&gt;
   Wire.write(&amp;quot;s&amp;quot;);&lt;br /&gt;
   Wire.endTransmission();&lt;br /&gt;
 }&lt;br /&gt;
 void LCD_address_go(byte display_position){&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(command_send);&lt;br /&gt;
   switch (display_position){&lt;br /&gt;
     case 0:&lt;br /&gt;
       Wire.write(0x80);//data position byte is one bit followed by 7 for address&lt;br /&gt;
       break;&lt;br /&gt;
     case 1:&lt;br /&gt;
       Wire.write(0x88);//eighth data position, first line&lt;br /&gt;
       break;&lt;br /&gt;
     case 2:&lt;br /&gt;
       Wire.write(0xC0);//second line begins at 0x40 (plus 0x80 for data position command)&lt;br /&gt;
       break;&lt;br /&gt;
     case 3:&lt;br /&gt;
       Wire.write(0xC8);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
   Wire.endTransmission();&lt;br /&gt;
 }&lt;br /&gt;
 void i2c_LCD_setup(){&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(command_send);&lt;br /&gt;
   Wire.write(B00111000);  //FUNCTION SET 8 bit, 2 line, not double-height, 0, instruction set zero&lt;br /&gt;
   delay(20);&lt;br /&gt;
   Wire.write(B00111001);  //FUNCTION SET 8 bit, 2 line, not double-height, 0, instruction set one&lt;br /&gt;
   delay(20);&lt;br /&gt;
   Wire.write(B00010100);  //OSC set 1/5 bias, frequency last three bits&lt;br /&gt;
   Wire.write(B01111111);  //Contrast set, four least significant contrast bits&lt;br /&gt;
   Wire.write(B01011101);  //Power/ICON set, Icon on, booster on, two most significant contrast bits&lt;br /&gt;
   Wire.write(B01101101);  //FOLLOWER CONTROL, follower on, last three bits follower amp ratio&lt;br /&gt;
   delay(300);  //Allow new voltage to stabilize from previous command.&lt;br /&gt;
   Wire.write(B00111000);  //Back to instruction set zero&lt;br /&gt;
   Wire.write(B00001100);  //DISPLAY ON, display on, cursor off, cursor position off&lt;br /&gt;
   Wire.write(1);  //Clear display&lt;br /&gt;
   Wire.write(B00000110);  //ENTRY MODE, increment cursor, don&#039;t shift display&lt;br /&gt;
   Wire.endTransmission();    // stop transmitting&lt;br /&gt;
 }&lt;br /&gt;
 void clear_LCD(){&lt;br /&gt;
   Wire.beginTransmission(LCD_address);&lt;br /&gt;
   Wire.write(command_send);&lt;br /&gt;
   Wire.write(1);  //Clear display&lt;br /&gt;
   Wire.endTransmission();    // stop transmitting&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2929</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2929"/>
		<updated>2025-03-31T02:13:22Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Code */ add easy copy button&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CircuitPython ==&lt;br /&gt;
CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line copy&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2928</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2928"/>
		<updated>2025-03-30T21:26:53Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Code */  fixing code preview&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CircuitPython ==&lt;br /&gt;
CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; line&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2927</id>
		<title>Photo-gate timer with CircuitPython</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer_with_CircuitPython&amp;diff=2927"/>
		<updated>2025-03-30T21:24:10Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Created page with &amp;quot;== CircuitPython == CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file. == ESP32-S2 Reverse TFT Feather == The ESP32-S2 Reverse TFT Feather from A...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CircuitPython ==&lt;br /&gt;
CircuitPython is a flavor or port of MicroPython, by Adafruit Industries, to program any of hundreds of micro-controllers or single-board-computers with Python code. Changing the code on a board is simple: You copy a Python program file, and optionally libraries, to board that can be set to present itself to a computer as a USB drive. When you reset the board, it runs the file.&lt;br /&gt;
== ESP32-S2 Reverse TFT Feather ==&lt;br /&gt;
The ESP32-S2 Reverse TFT Feather from Adafruit, https://www.adafruit.com/product/5345 , is an inexpensive development board with a WiFi capable&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
import time&lt;br /&gt;
import board&lt;br /&gt;
import keypad&lt;br /&gt;
print(&amp;quot;Photogate timer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gates = (board.D1, board.D2)&lt;br /&gt;
#create empty list:&lt;br /&gt;
times = []&lt;br /&gt;
#track which gates have already been interrupted&lt;br /&gt;
passed = []&lt;br /&gt;
#interval is time in seconds to debounce button.&lt;br /&gt;
keys = keypad.Keys(gates, value_when_pressed=True, pull=True, interval=0.002)&lt;br /&gt;
while True:&lt;br /&gt;
    event=keys.events.get()&lt;br /&gt;
    if event:&lt;br /&gt;
        #print(event) #uncomment this to debug events&lt;br /&gt;
        #which gate was passed? event.key_number&lt;br /&gt;
        #if this is the first gate:&lt;br /&gt;
        if 0 == len(times):&lt;br /&gt;
            times.append(0.0)&lt;br /&gt;
            startTime = time.monotonic()&lt;br /&gt;
            #mark which gate has been passed&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
        #else check if a gate not yet passed:&lt;br /&gt;
        elif 0 == passed.count(event.key_number):&lt;br /&gt;
            #Add the current time to the list&lt;br /&gt;
            times.append(time.monotonic() - startTime)&lt;br /&gt;
            passed.append(event.key_number)&lt;br /&gt;
            print(times)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2926</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2926"/>
		<updated>2025-03-30T21:12:16Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Program */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For examples, see [[Photo-gate timer with an Arduino]] or [[Photo-gate timer with CircuitPython]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller:http://www.atmel.com/devices/ATMEGA328P.aspx&lt;br /&gt;
;PICAXE micro-controller system for education:http://picaxe.com&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter:http://optoelectronics.liteon.com/upload/download/DS-50-92-0009/P_100_E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor:http://optoelectronics.liteon.com/upload/download/DS-50-93-0013/P_100_LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2925</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2925"/>
		<updated>2025-03-29T20:46:02Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|256px|thumb|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For an explicit example, see [[Photo-gate timer with an Arduino]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller:http://www.atmel.com/devices/ATMEGA328P.aspx&lt;br /&gt;
;PICAXE micro-controller system for education:http://picaxe.com&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter:http://optoelectronics.liteon.com/upload/download/DS-50-92-0009/P_100_E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor:http://optoelectronics.liteon.com/upload/download/DS-50-93-0013/P_100_LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2924</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2924"/>
		<updated>2025-03-29T20:45:14Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Components */ Diagram of angular dependence of sensitivity&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
[[File:LTR-301-fov.png|right|The sensitivity of the 301 is very dependent on the angle of incidence of light. This helps mitigate interference, but one must be careful to aim the phototransistor.]]&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For an explicit example, see [[Photo-gate timer with an Arduino]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller:http://www.atmel.com/devices/ATMEGA328P.aspx&lt;br /&gt;
;PICAXE micro-controller system for education:http://picaxe.com&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter:http://optoelectronics.liteon.com/upload/download/DS-50-92-0009/P_100_E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor:http://optoelectronics.liteon.com/upload/download/DS-50-93-0013/P_100_LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=File:LTR-301-fov.png&amp;diff=2923</id>
		<title>File:LTR-301-fov.png</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=File:LTR-301-fov.png&amp;diff=2923"/>
		<updated>2025-03-29T20:43:12Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Sensitivity of the LiteON LTR 301 phototransistor by angle from forward.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Sensitivity of the LiteON LTR 301 phototransistor by angle from forward.&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2922</id>
		<title>Mini vMac</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2922"/>
		<updated>2025-03-28T13:38:42Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Alternatives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Mini VMac allows users of newer Macs to run a Macintosh Plus in a window on their computer. http://minivmac.sourceforge.net/doc/start.html&lt;br /&gt;
&lt;br /&gt;
=== Versions ===&lt;br /&gt;
You need to run a version of Mini vMac compiled to match the ROMs you use. For example, since I&#039;m getting my ROMs from a Mac SE FDHD, I have to use version 24, compiled to match the capabilities of an SE FDHD, and to run on my (Intel) PowerBook Pro. You can get many variations here: http://minivmac.sourceforge.net/doc/var/index.html&lt;br /&gt;
&lt;br /&gt;
=== CopyRoms ===&lt;br /&gt;
http://minivmac.sourceforge.net/extras/copyroms.html&lt;br /&gt;
&lt;br /&gt;
To run Mini VMac, you need a copy of ROMs from a 680x0 Mac, (from Mac 128, the original, to Mac II). What is difficult to find is how to get a copy of CopyRoms running in an old mac. Instead of providing a program to copy onto a disk, the authors provide a raw disk image with the program on it. Nowhere in the guides do authors tell you how to get the provided image onto a disk so you can put the disk in an old Mac and run CopyRoms. One way to do it is to use dd in linux or OS X. First, you should insert a floppy in a connected drive, then in a terminal (shell), you should use the mount command to find out what the name of the floppy device is. In my case, I type mount, and I see many lines, one line being&lt;br /&gt;
 /dev/disk1 on /Volumes/Unlabeled (local, nodev, nosuid)&lt;br /&gt;
Since my floppy was called Unlabeled, I know this is it, so I use dd to copy the CopyRoms disk image to it. But to access a drive at the base level, it needs to be unmounted (else a &amp;quot;device busy&amp;quot; error), so use Disk Utility to unmount the volume, but don&#039;t eject it. Then go back to terminal and enter the following command, being sure to substitute your floppy device name for the last argument (mine was /dev/disk1, but yours may be different).&lt;br /&gt;
 dd bs=2x80x18b &amp;lt; /path-to/copyroms-1.1.0.dsk &amp;gt; ( your floppy device name)&lt;br /&gt;
WARNING! If you put the wrong device at the end of that command, you could mess up your hard drive forever. Make sure you don&#039;t type the wrong device. disk1 in your case might be a hard drive or anything, so make sure to use the mount command first to find the right device. It would be best, instead of typing it, to copy and paste from the output of mount, and still double-check.&lt;br /&gt;
&lt;br /&gt;
I had a problem, CopyRoms was not making a non-zero rom file in my SE FDHD. I realized the problem was that when I used dd to copy the image to the floppy, it made a floppy with only a bit more capacity than the image, so there was no room for CopyRoms to place the rom file onto the disk. When I copied CopyRoms to the hard drive in my SE, it worked. Another workaround would be, once you&#039;ve made the floppy, copy the program onto your hard drive, reformat the floppy to full size, then copy CopyRoms back onto the floppy. Reformatting works in Snow Leopard, but Jaguar can&#039;t format floppies.&lt;br /&gt;
&lt;br /&gt;
=== System Software ===&lt;br /&gt;
The authors of Mini vMac suggest getting System 6.0.8 software from Apple: http://www.info.apple.com/support/oldersoftwarelist.html You&#039;ll need Stuffit Expander to expand the SEA archives. Stuffit Expander is free from Smith Micro: http://www.stuffit.com/mac-expander.html&lt;br /&gt;
&lt;br /&gt;
=== Alternatives ===&lt;br /&gt;
[https://infinitemac.org Infinite Mac] offers various Mac OS 10 and NeXT computers that run in a web browser. Now you can have NeXT on your phone, so you can frustrate yourself with awkward awk functions.&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2921</id>
		<title>Mini vMac</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2921"/>
		<updated>2025-03-28T13:36:24Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Reformatting headers. Added alternatives section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Mini VMac allows users of newer Macs to run a Macintosh Plus in a window on their computer. http://minivmac.sourceforge.net/doc/start.html&lt;br /&gt;
&lt;br /&gt;
=== Versions ===&lt;br /&gt;
You need to run a version of Mini vMac compiled to match the ROMs you use. For example, since I&#039;m getting my ROMs from a Mac SE FDHD, I have to use version 24, compiled to match the capabilities of an SE FDHD, and to run on my (Intel) PowerBook Pro. You can get many variations here: http://minivmac.sourceforge.net/doc/var/index.html&lt;br /&gt;
&lt;br /&gt;
=== CopyRoms ===&lt;br /&gt;
http://minivmac.sourceforge.net/extras/copyroms.html&lt;br /&gt;
&lt;br /&gt;
To run Mini VMac, you need a copy of ROMs from a 680x0 Mac, (from Mac 128, the original, to Mac II). What is difficult to find is how to get a copy of CopyRoms running in an old mac. Instead of providing a program to copy onto a disk, the authors provide a raw disk image with the program on it. Nowhere in the guides do authors tell you how to get the provided image onto a disk so you can put the disk in an old Mac and run CopyRoms. One way to do it is to use dd in linux or OS X. First, you should insert a floppy in a connected drive, then in a terminal (shell), you should use the mount command to find out what the name of the floppy device is. In my case, I type mount, and I see many lines, one line being&lt;br /&gt;
 /dev/disk1 on /Volumes/Unlabeled (local, nodev, nosuid)&lt;br /&gt;
Since my floppy was called Unlabeled, I know this is it, so I use dd to copy the CopyRoms disk image to it. But to access a drive at the base level, it needs to be unmounted (else a &amp;quot;device busy&amp;quot; error), so use Disk Utility to unmount the volume, but don&#039;t eject it. Then go back to terminal and enter the following command, being sure to substitute your floppy device name for the last argument (mine was /dev/disk1, but yours may be different).&lt;br /&gt;
 dd bs=2x80x18b &amp;lt; /path-to/copyroms-1.1.0.dsk &amp;gt; ( your floppy device name)&lt;br /&gt;
WARNING! If you put the wrong device at the end of that command, you could mess up your hard drive forever. Make sure you don&#039;t type the wrong device. disk1 in your case might be a hard drive or anything, so make sure to use the mount command first to find the right device. It would be best, instead of typing it, to copy and paste from the output of mount, and still double-check.&lt;br /&gt;
&lt;br /&gt;
I had a problem, CopyRoms was not making a non-zero rom file in my SE FDHD. I realized the problem was that when I used dd to copy the image to the floppy, it made a floppy with only a bit more capacity than the image, so there was no room for CopyRoms to place the rom file onto the disk. When I copied CopyRoms to the hard drive in my SE, it worked. Another workaround would be, once you&#039;ve made the floppy, copy the program onto your hard drive, reformat the floppy to full size, then copy CopyRoms back onto the floppy. Reformatting works in Snow Leopard, but Jaguar can&#039;t format floppies.&lt;br /&gt;
&lt;br /&gt;
=== System Software ===&lt;br /&gt;
The authors of Mini vMac suggest getting System 6.0.8 software from Apple: http://www.info.apple.com/support/oldersoftwarelist.html You&#039;ll need Stuffit Expander to expand the SEA archives. Stuffit Expander is free from Smith Micro: http://www.stuffit.com/mac-expander.html&lt;br /&gt;
&lt;br /&gt;
=== Alternatives ===&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2920</id>
		<title>Mini vMac</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Mini_vMac&amp;diff=2920"/>
		<updated>2025-03-28T13:35:10Z</updated>

		<summary type="html">&lt;p&gt;Shawn: put in Computers category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Mini VMac allows users of newer Macs to run a Macintosh Plus in a window on their computer. http://minivmac.sourceforge.net/doc/start.html&lt;br /&gt;
&lt;br /&gt;
;Versions&lt;br /&gt;
You need to run a version of Mini vMac compiled to match the ROMs you use. For example, since I&#039;m getting my ROMs from a Mac SE FDHD, I have to use version 24, compiled to match the capabilities of an SE FDHD, and to run on my (Intel) PowerBook Pro. You can get many variations here: http://minivmac.sourceforge.net/doc/var/index.html&lt;br /&gt;
&lt;br /&gt;
;CopyRoms&lt;br /&gt;
http://minivmac.sourceforge.net/extras/copyroms.html&lt;br /&gt;
&lt;br /&gt;
To run Mini VMac, you need a copy of ROMs from a 680x0 Mac, (from Mac 128, the original, to Mac II). What is difficult to find is how to get a copy of CopyRoms running in an old mac. Instead of providing a program to copy onto a disk, the authors provide a raw disk image with the program on it. Nowhere in the guides do authors tell you how to get the provided image onto a disk so you can put the disk in an old Mac and run CopyRoms. One way to do it is to use dd in linux or OS X. First, you should insert a floppy in a connected drive, then in a terminal (shell), you should use the mount command to find out what the name of the floppy device is. In my case, I type mount, and I see many lines, one line being&lt;br /&gt;
 /dev/disk1 on /Volumes/Unlabeled (local, nodev, nosuid)&lt;br /&gt;
Since my floppy was called Unlabeled, I know this is it, so I use dd to copy the CopyRoms disk image to it. But to access a drive at the base level, it needs to be unmounted (else a &amp;quot;device busy&amp;quot; error), so use Disk Utility to unmount the volume, but don&#039;t eject it. Then go back to terminal and enter the following command, being sure to substitute your floppy device name for the last argument (mine was /dev/disk1, but yours may be different).&lt;br /&gt;
 dd bs=2x80x18b &amp;lt; /path-to/copyroms-1.1.0.dsk &amp;gt; ( your floppy device name)&lt;br /&gt;
WARNING! If you put the wrong device at the end of that command, you could mess up your hard drive forever. Make sure you don&#039;t type the wrong device. disk1 in your case might be a hard drive or anything, so make sure to use the mount command first to find the right device. It would be best, instead of typing it, to copy and paste from the output of mount, and still double-check.&lt;br /&gt;
&lt;br /&gt;
I had a problem, CopyRoms was not making a non-zero rom file in my SE FDHD. I realized the problem was that when I used dd to copy the image to the floppy, it made a floppy with only a bit more capacity than the image, so there was no room for CopyRoms to place the rom file onto the disk. When I copied CopyRoms to the hard drive in my SE, it worked. Another workaround would be, once you&#039;ve made the floppy, copy the program onto your hard drive, reformat the floppy to full size, then copy CopyRoms back onto the floppy. Reformatting works in Snow Leopard, but Jaguar can&#039;t format floppies.&lt;br /&gt;
&lt;br /&gt;
;System Software&lt;br /&gt;
The authors of Mini vMac suggest getting System 6.0.8 software from Apple: http://www.info.apple.com/support/oldersoftwarelist.html You&#039;ll need Stuffit Expander to expand the SEA archives. Stuffit Expander is free from Smith Micro: http://www.stuffit.com/mac-expander.html&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2919</id>
		<title>Photo-gate timer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Photo-gate_timer&amp;diff=2919"/>
		<updated>2025-03-27T16:51:13Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Components */ picture of individual photo-gate&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Photo-gate-timer-2014-03-11.jpg|512px|thumb|right|A photo-gate timer featuring an LCD display, showing 3 of 5 possible gates at left. In a working lab, the LEDs and photo-transistors would have to be attached to the board via long wires so they could be placed usefully.]]&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Connect up to 5 gates for four times (first gate zeros timer).&lt;br /&gt;
*Include a display with enough characters to show the time past each connected gate, 8x2 or 16x2.&lt;br /&gt;
*Include a power switch to save the battery, and/or a reset switch.&lt;br /&gt;
*Use a breadboard so it can be built by students, or modified.&lt;br /&gt;
*Allow timing of periods up to at least 10s, accurate to 0.01s.&lt;br /&gt;
&lt;br /&gt;
===Circuit===&lt;br /&gt;
[[File:Photo-gate-timer-Arduino.png|512px|thumb|right|Circuit diagram for a photo-gate timer featuring an LCD display.]]&lt;br /&gt;
This circuit is built in sections, the micro-controller and display on one breadboard and each gate on their own separate ones, with three lines (V+, ground, and signal) going between. The three-volt supply may involve a voltage-regulator circuit, which optionally would include a diode to protect from backwards-connected supplies.&lt;br /&gt;
&lt;br /&gt;
For a printable diagram of the Atmega 328P-version of this circuit, see [[Media:Photo-gate-timer-Arduino.pdf|Photo-gate-timer-Arduino.pdf]].&lt;br /&gt;
&lt;br /&gt;
For a less-accurate PICAXE version of this circuit, see [[Media:PICAXE-Photo-gate-timer-i2c-LCD-2014.png|PICAXE-Photo-gate-timer-i2c-LCD-2014.png]] .&lt;br /&gt;
&lt;br /&gt;
====Photo-gate====&lt;br /&gt;
[[File:Infrared-photogate-circuit-diagrams.png|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
The higher the resistance of the resistor feeding the photo-transistor, the higher its sensitivity, but the slower its response will be. For an extremely sensitive receiver, calibrate an op-amp as a comparator—It would have to be re-calibrated every time the environment changes.&lt;br /&gt;
&lt;br /&gt;
Often the micro-controller features an internal pull-up resistor on its inputs. If activated, the circuit will use less power if the photo-gates are designed to be active-low instead of active-high, since most of the time they&#039;ll be inactive and thus not drawing current through the pull-up resistors.&lt;br /&gt;
&lt;br /&gt;
===Components===&lt;br /&gt;
[[File:Photogate-mini-breadboard.jpeg|256px|thumb|right|Circuit diagram for photo-gates that put out either high or low when blocked.]]&lt;br /&gt;
&lt;br /&gt;
*Photogates&lt;br /&gt;
**LED, infrared (~$0.15). I use a Lite-On LTE-302-M, which has a black or gold dot to identify itself as an emitter; it also allows up to 50mA of constant current, or even 1A if pulsed 300 10µs pulses per second, so it can be used at a greater distance than 20mA emitters. The cathode is the short lead, on the left as you&#039;re facing the lens.&lt;br /&gt;
**Phototransistor, infrared (~$0.15). I use a Lite-On LTR-301, which has a red dot to identify itself as a receiver. The collector is the long lead, on the right as you&#039;re facing the lens, the short lead being the emitter of the transistor.&lt;br /&gt;
**Switching transistor, 2N2222 or equivalent NPN  (~$0.10). I use an R3309, whose leads are emitter, collector, and base, left to right, as seen leading down when looking at the flat face.&lt;br /&gt;
**Resistors&lt;br /&gt;
***LED limiting resistor (4V/40mA=100Ω; 4V/20mA=200Ω; 2V/40mA=50Ω)  (~$0.02)&lt;br /&gt;
***Phototransistor resistor (~5kΩ)  (~$0.02)&lt;br /&gt;
***NPN base resistor (~50kΩ)  (~$0.02)&lt;br /&gt;
***NPN emitter resistor (~1kΩ)  (~$0.02)&lt;br /&gt;
*Breadboard (~$5)&lt;br /&gt;
*Micro-controller. I use a PICAXE 20M2 (software timing) or a 20X2 (dedicated hardware timing for better accuracy); both have plenty of inputs and outputs for multiple gates and any type of display. ($4-$6)&lt;br /&gt;
**Resonator circuit if necessary. Not available for PICAXE 20M2. (~$1)&lt;br /&gt;
*Display&lt;br /&gt;
**LCD Display, serial capable. I use Newhaven&#039;s NHD-C0216CiZ-FSW-FBW-3V3 LCD with I2C ($10)&lt;br /&gt;
***Two 1µF capacitors to aid voltage booster circuit.&lt;br /&gt;
***Two 5kΩ resistors to pull up serial clock and data lines while idle.&lt;br /&gt;
***One 50kΩ resistor to pull up reset.&lt;br /&gt;
**Alternatively, a TTL-to-USB or TTL-to-serial circuit for sharing data with computer ($18)&lt;br /&gt;
*Hook-up wires ($2)&lt;br /&gt;
*Power supply&lt;br /&gt;
**9V or a quartet of AAA with a 3V voltage regulator, capacitor(s), resistor(s), or&lt;br /&gt;
**3V AC adapter, or&lt;br /&gt;
**Two alkaline AAA or AA batteries.&lt;br /&gt;
&lt;br /&gt;
====Saving power====&lt;br /&gt;
The LCD and micro-controller use little power compared to the infrared emitters, which are constantly on in this circuit as initially designed. So, one way to significantly reduce power would be to power only the next-expected-to-close gate. Another way to reduce power would be to pulse the emitters, which would also allow for very bright IR light—This way would require periodic pulses of narrow width accompanied by polling of the receiving circuit, or a more elaborate circuit involving a missing-pulse detector, a timer at each photogate that is reset by pulses from the emitter. Pulses and delays in timing would limit the precision of the system.&lt;br /&gt;
&lt;br /&gt;
===Program===&lt;br /&gt;
For an explicit example, see [[Photo-gate timer with an Arduino]] or the less-accurate [[Photo-gate timer with a PICAXE 20M2]].&lt;br /&gt;
#Initiate the display&lt;br /&gt;
#Write &amp;quot;waiting for 1st gate&amp;quot; to the display&lt;br /&gt;
#Set an interrupt on the pin attached to the first gate. Will interrupt the program wherever execution is and go to Interrupt.&lt;br /&gt;
#Loop.&lt;br /&gt;
##Increment time counter.&lt;br /&gt;
##Go back to Loop.&lt;br /&gt;
#Interrupt&lt;br /&gt;
##If first gate:&lt;br /&gt;
###Reset counter.&lt;br /&gt;
###Display &amp;quot;1st gate tripped&amp;quot;.&lt;br /&gt;
###Set interrupt to second gate, or all the rest of the gates to allow four independent channels of timing.&lt;br /&gt;
##If other gate:&lt;br /&gt;
###Save counter as time for that gate.&lt;br /&gt;
###Display that value in the place corresponding to that gate.&lt;br /&gt;
###Set interrupt to next gate unless this is the last one or running interrupt on all gates.&lt;br /&gt;
##Return to wherever program was before interrupt.&lt;br /&gt;
&lt;br /&gt;
===Datasheets===&lt;br /&gt;
[[File:1.5mm pitch pins soldered onto 2.5mm header.jpg|300px|thumbnail|right|Showing the 8 pins of the Newhaven LCD spread to fit onto a 0.1&amp;quot; pitch header, so as to be easily inserted into a solderless breadboard.]]&lt;br /&gt;
;Newhaven Display liquid crystal display module, with side white backlight and transflective display.:http://www.newhavendisplay.com/specs/NHD-C0216CiZ-FSW-FBW-3V3.pdf&lt;br /&gt;
;Atmel 328P 8-bit microcontroller:http://www.atmel.com/devices/ATMEGA328P.aspx&lt;br /&gt;
;PICAXE micro-controller system for education:http://picaxe.com&lt;br /&gt;
;Lite-on LTE-302 side-look IR emitter:http://optoelectronics.liteon.com/upload/download/DS-50-92-0009/P_100_E302.pdf&lt;br /&gt;
;Lite-on LTR-301 side-look IR photo-transistor:http://optoelectronics.liteon.com/upload/download/DS-50-93-0013/P_100_LTR-301.pdf&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
See more discussion and other circuits at [[Circuits for teaching physics]].&lt;br /&gt;
&lt;br /&gt;
For a discussion of the circuit around the photo-transistor, read &#039;&#039;An Arduino-Controlled Photogate&#039;&#039; by Calin Galeriu of Becker College, Worcester, Massachusetts, in The Physics Teacher, v51:n3:pp156-158. http://dx.doi.org/10.1119/1.4792011&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=File:Photogate-mini-breadboard.jpeg&amp;diff=2918</id>
		<title>File:Photogate-mini-breadboard.jpeg</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=File:Photogate-mini-breadboard.jpeg&amp;diff=2918"/>
		<updated>2025-03-27T16:47:33Z</updated>

		<summary type="html">&lt;p&gt;Shawn: A solderless breadboard with LED and phototransistor facing each other, with supporting resistors and transistor to form a photo-gate circuit.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
A solderless breadboard with LED and phototransistor facing each other, with supporting resistors and transistor to form a photo-gate circuit.&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Phones&amp;diff=2917</id>
		<title>Phones</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Phones&amp;diff=2917"/>
		<updated>2025-03-17T19:06:33Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Camera phones and near infrared ==&lt;br /&gt;
Older camera phones didn&#039;t have enough pixels for the [https://en.m.wikipedia.org/wiki/Chromatic_aberration chromatic aberration] of infrared light combined with visible light to be significant. But now that the aberration spreads across multiple pixels of high-resolution sensors, cameras require an infrared filter. You can point low-resolution camera at the emitter of a remote control, most of which use infrared light, to see the pattern of light being emitted. A high-resolution camera will not sense the light.&lt;br /&gt;
&lt;br /&gt;
== Sonim XP phones ==&lt;br /&gt;
I was annoyed at how whenever I accidentally pressed the yellow side button, the TDC app would start. I learned from a discussion at T-Mobile support site, https://www.t-mobile.com/community/discussions/devices-orders/sonim-xp3plus-issues-apps-how-to-stop-direct-connect-asking-me-to-activate/132775 , that I could assign the yellow button to any app, so I assigned it to Calculator, and now it opens Calculator if phone is open and does nothing if phone is closed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Options &amp;gt; System settings &amp;gt; System &amp;gt; Programmable Keys &amp;gt; Select PTT Key app&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Phones]] [[Category:How-to]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Phones&amp;diff=2916</id>
		<title>Phones</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Phones&amp;diff=2916"/>
		<updated>2025-03-17T19:01:54Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Created page with &amp;quot;== Sonim XP phones == I was annoyed at how whenever I accidentally pressed the yellow side button, the TDC app would start. I learned from a discussion at T-Mobile support sit...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sonim XP phones ==&lt;br /&gt;
I was annoyed at how whenever I accidentally pressed the yellow side button, the TDC app would start. I learned from a discussion at T-Mobile support site, https://www.t-mobile.com/community/discussions/devices-orders/sonim-xp3plus-issues-apps-how-to-stop-direct-connect-asking-me-to-activate/132775 , that I could assign the yellow button to any app, so I assigned it to Calculator, and now it opens Calculator if phone is open and does nothing if phone is closed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Options &amp;gt; System settings &amp;gt; System &amp;gt; Programmable Keys &amp;gt; Select PTT Key app&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Phones]] [[Category:How-to]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Traveling_with_a_telephone&amp;diff=2915</id>
		<title>Traveling with a telephone</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Traveling_with_a_telephone&amp;diff=2915"/>
		<updated>2025-03-17T18:55:34Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Removing outdated information&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AT&amp;amp;T Wireless==&lt;br /&gt;
To dial from France back to the U.S. or any U.S. number, dial 001- area code and number. To dial within the country dial locally. To listen to voice mails press and hold down the 1 key, follow the prompts, interrupt the greeting by pressing the (*) key, enter your voice mail password. The per minute rate applies for listening to your voice mails, also, if your phone is ON and someone calls you or leaves you a voice mail the per minute rate will also apply. In order to avoid these charges have your phone OFF when not in use.&lt;br /&gt;
&lt;br /&gt;
===iPhone===&lt;br /&gt;
Use network calling apps like Zoom/Webex when in WiFi range.&lt;br /&gt;
&lt;br /&gt;
Be sure to turn off any features you don&#039;t need, such as push email, contacts, and calendar. Or, use Airplane mode with WiFi on to turn off just the use of the phone lines for data retrieval.&lt;br /&gt;
&lt;br /&gt;
Your line may have the standard international feature at $0 per month and some amount per minute to make or receive calls while traveling in another country.&lt;br /&gt;
&lt;br /&gt;
AT&amp;amp;T offers the discounted rate at $x per month and $y per minute to make or receive calls in France.&lt;br /&gt;
&lt;br /&gt;
Look for data plans.&lt;br /&gt;
&lt;br /&gt;
[[Category:Travel]] [[Category:Phones]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Webmaster_recipes&amp;diff=2914</id>
		<title>Webmaster recipes</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Webmaster_recipes&amp;diff=2914"/>
		<updated>2025-03-16T02:39:42Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Added hits per minute&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Detect heavy users in logs===&lt;br /&gt;
 cat access.log | cut -d&amp;quot; &amp;quot; -f1|sort | uniq -c | sort -r|head&lt;br /&gt;
===Count access to each file, ignoring URL parameters===&lt;br /&gt;
 cat access.log |cut -d&amp;quot; &amp;quot; -f7|cut -d&amp;quot;?&amp;quot; -f1|sort|uniq -c&lt;br /&gt;
===Count access from an IP prefix===&lt;br /&gt;
 grep -c &amp;quot;^xxx.xxx.&amp;quot; access.log&lt;br /&gt;
===Count hits per minute===&lt;br /&gt;
 cut -d&amp;quot; &amp;quot; -f4 access.log|cut -d&amp;quot;:&amp;quot; -f2,3|sort|uniq -c&lt;br /&gt;
===Dealing with hotlinking===&lt;br /&gt;
Hot-linking is the use of links to content at one site, usually images, by pages on another site. At first, page-designers may have used links to images on other sites because they couldn&#039;t create useful images themselves. These days, robots are made to make pages with random content, using both content and images from around the world to create a site in the hopes of fooling search engines into thinking that the site contains useful information on specific topics.&lt;br /&gt;
&lt;br /&gt;
====Searching logs for hotlinkers====&lt;br /&gt;
 awk &#039;{if ($7 !~ /\.(jpe?g|gif|png)$/) next;&lt;br /&gt;
 if ($11 ~ /^&amp;quot;https?:\/\/[^\/]*energyteachers.org/) next;&lt;br /&gt;
 if ($11 ~ /&amp;quot;-&amp;quot;/) next;&lt;br /&gt;
 print $11;}&#039; access_log* |sort|uniq -c|sort&lt;br /&gt;
;Explanation&lt;br /&gt;
*$7 refers to the seventh segment of the log, split by spaces, which contains the request.&lt;br /&gt;
*!~ means &amp;quot;does not contain the following expression&amp;quot;&lt;br /&gt;
*The expression between the slashes finds text that include a dot followed by one of the image extensions. The dollar sign signifies the end of the request.&lt;br /&gt;
*So, the first line of if...next tell awk to skip lines that aren&#039;t requests for image files.&lt;br /&gt;
*The second line skips references from energyteachers.org&lt;br /&gt;
*The third line skips empty references, allowing people to bookmark images or type their addresses in their browser.&lt;br /&gt;
*The fourth line prints the reference, and after finishing the awk command set, contains the wildcard-appended log-file-name to be processed, followed by a sort, then a count of how many times that reference was used, then sorting by that count.&lt;br /&gt;
&lt;br /&gt;
====Preventing hot-linking of images====&lt;br /&gt;
&lt;br /&gt;
There are hundreds of pages telling how to turn away hot-linkers using Apache&#039;s Rewrite module, but Apache suggests you use their built-in directives when possible, and this is one of those cases. So, I found a different way, thanks to the [http://wiki.apache.org/httpd/DisableImageHotLinking wiki] at apache.org.&lt;br /&gt;
 SetEnvIfNoCase Referer &amp;quot;^https?://([^/]*)?shawnreeves\.net/&amp;quot; local_ref=1&lt;br /&gt;
 SetEnvIf Referer ^$ local_ref=1&lt;br /&gt;
 &amp;lt;FilesMatch &amp;quot;\.(jpe?g|gif|png)$&amp;quot;&amp;gt;&lt;br /&gt;
  Order Allow,Deny&lt;br /&gt;
  Allow from env=local_ref&lt;br /&gt;
 &amp;lt;/FilesMatch&amp;gt;&lt;br /&gt;
#The first line uses a regular expression to match referrers that begin with http, with an optional s, followed by ://, then any number of non-slash characters, then the allowed domain (note the backslash to escape the period which normally is a wildcard). If the match is true, then an environmental variable local_ref is set to 1.&lt;br /&gt;
#The second line sets the local_ref variable to 1 if there is no referrer, such as when someone browses at an image from a bookmark or uses curl or some special tool for the blind.&lt;br /&gt;
#The third through sixth lines apply only if the files requested have image-type extensions.&lt;br /&gt;
#The fifth line allows such requests from anyone with the proper reference, leaving the rest to be denied by the order of the fourth line.&lt;br /&gt;
&lt;br /&gt;
===Multiple whois lookups===&lt;br /&gt;
I recently launched a new project at EnergyTeachers.org, [http://energyteachers.org/greendollhousechallenge.php Green Dollhouse Challenge], and I wanted to see who responded to a group email I posted about it. I downloaded the logs and retrieved the list of IP addresses that accessed the page with this command which searches for the word dollhouse in the server&#039;s log, taking just the first section which is the IP address, then sorting which is required for uniq, then listing only unique addresses with a count of how many visits came from each address:&lt;br /&gt;
 grep dollhouse access_log.2011-03-29|cut -d &amp;quot; &amp;quot; -f1| sort|uniq -c&lt;br /&gt;
I was taking each resulting IP and copying and pasting it after typing whois in another shell to find clues to whether the visitor was a search spider or a real person. I learned (from http://www.tek-tips.com/viewthread.cfm?qid=1566237&amp;amp;page=7 ) that I could use an inline text editor to type &amp;quot;whois &amp;quot; and the result from the above command, without the count, and then pass that to a shell within this shell to process each line as a command:&lt;br /&gt;
 grep dollhouse access_log.2011-03-29 | cut -d &amp;quot; &amp;quot; -f1&lt;br /&gt;
 | sort | uniq | awk &#039;{print &amp;quot;whois &amp;quot; $1}&#039; | sh&lt;br /&gt;
awk takes each line, prepends &amp;quot;whois &amp;quot;, and then sends it to the shell &amp;quot;sh&amp;quot; to process.&lt;br /&gt;
===Search queries===&lt;br /&gt;
Open a terminal and go to a directory full of Apache log files. Enter the following command (all on one line):&lt;br /&gt;
 egrep -r -h -o &amp;quot;.*q=[^&amp;amp;]*&amp;quot; ./*&lt;br /&gt;
 |awk &#039;{print $1&amp;quot;\t&amp;quot;substr($11,match($11,&amp;quot;q=&amp;quot;)+2)}&#039;&lt;br /&gt;
 |php -R &#039;echo substr(urldecode($argn),stripos($argn,&amp;quot;&amp;amp;&amp;quot;)).&amp;quot;\n&amp;quot;;&#039;&lt;br /&gt;
 &amp;gt; ../SearchQueriesIP.txt&lt;br /&gt;
Egrep will go through all the files in the folder (-r and ./*); find strings that have q= up to the next ampersand, which is usually how a search engine reports the query string that someone entered before they clicked on a result to get to our site; only output the matching part (-o); and skip listing the filename from the match (-h).&lt;br /&gt;
&lt;br /&gt;
Next, awk picks the IP address of the visitor ($1), a tab (\t), and then the query string ($11), leaving out the first two characters (q=). PHP then takes each line ($argn) and decodes the text, changing plus signs to spaces and so on. It also removes any unexplained extra bits following ampersands; this will become unnecessary when I figure out how some ampersands are slipping through.&lt;br /&gt;
&lt;br /&gt;
Finally, the results are saved to a file using the redirect symbol (&amp;gt;), in the next directory up (../) so egrep doesn&#039;t search its own output.&lt;br /&gt;
&lt;br /&gt;
====Issues with this analysis====&lt;br /&gt;
;q= might be in the request:If the request string includes the string q=, then this would return that request instead of the referrer&#039;s query. A solution may be to use awk instead of grep, only checking the 11th field.&lt;br /&gt;
;Analysis of requests:This doesn&#039;t output or process the request field. Easy enough to fix, we could just add field $7 to the print command in awk, or some significant substring of $9.&lt;br /&gt;
&lt;br /&gt;
It&#039;s a little sad to see so many people type energyteachers.org into google instead of directly into the address area of the browser. I guess Google has no problem being seen as the gateway to the internet, even with the futile bandwidth usage.&lt;br /&gt;
&lt;br /&gt;
====Better performing with awk====&lt;br /&gt;
Here&#039;s a more awkward process, but it only has one pipe.&lt;br /&gt;
 awk &#039;{if ($11 !~ /q=/) next;&lt;br /&gt;
 split($11,queries,&amp;quot;=&amp;quot;);&lt;br /&gt;
 for (var in queries) if (match(queries[var],/q$/)) searched=queries[var+1];&lt;br /&gt;
 print $1&amp;quot;\t&amp;quot;$7&amp;quot;\t&amp;quot;substr(searched,1,match(searched,&amp;quot;&amp;amp;&amp;quot;)-1)}&#039; access_log*&lt;br /&gt;
 |php -R &#039;echo urldecode($argn).&amp;quot;\n&amp;quot;;&#039;&lt;br /&gt;
The first line skips input lines that don&#039;t have &amp;quot;q=&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The second line splits the referrer line by equal signs, essentially separating fields, into an array &amp;quot;queries&amp;quot;. The third line looks for the item in queries that ends with q, setting our target to the next item in the array, since it must follow &amp;quot;q=&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The fourth line prints the IP address of the requester, the page requested, and search query. The fifth line takes each line ($argn) and decodes the text, changing plus signs to spaces and so on.&lt;br /&gt;
===Popularity of a page over time===&lt;br /&gt;
 awk &#039;$1 !~&amp;quot;MY_WORK_IP&amp;quot; &amp;amp;&amp;amp; $7 ~ /PAGE_NAME/ \&lt;br /&gt;
 {print substr($4,5,3)&amp;quot; &amp;quot;substr($4,2,2)}&#039; access* |uniq -c&lt;br /&gt;
This script skips all requests from my own IP, so I don&#039;t count my own hits, includes all requests for a certain PAGE_NAME or subset of pages with a certain text in their name, and returns the month and date, then counts how many hits there are each date. Note the backslash at the end of the first line is not part of the awk script but just a way to split this shell command into two lines. I.e., if you use it on one line, remove the backslash.&lt;br /&gt;
===Track logs according to hit===&lt;br /&gt;
Sometimes I want to see what people do when after or before they hit a certain page. With the following line, broken into readable chunks by back-slashes, of shell commands, I can search Apache logs to see the activity of anyone who hits a given page.&lt;br /&gt;
 grep -rh &amp;quot;GET /ENTRY_PAGE_EXAMPLE&amp;quot; . | \&lt;br /&gt;
 cut -d &amp;quot; &amp;quot; -f 1| \&lt;br /&gt;
 sort|uniq| \&lt;br /&gt;
 awk &#039;{print &amp;quot;echo &amp;quot;$1&amp;quot;;grep -rh &amp;quot; $1&amp;quot; \.&amp;quot;}&#039; | \&lt;br /&gt;
 sh&amp;gt;../ENTRY_PAGE_EXAMPLE-viewers.txt&lt;br /&gt;
#Grep searches all files in the current directory for a request for whatever page.&lt;br /&gt;
#Cut selects just the first item, which should be the IP address of the browser.&lt;br /&gt;
#Sort and uniq pass just one copy of each IP address that comes through.&lt;br /&gt;
#Awk creates a command to print a list of accesses from each IP address.&lt;br /&gt;
##Echo will print the IP address on a line, as a header to help readability.&lt;br /&gt;
##Grep will find all occurrences of each IP address.&lt;br /&gt;
#Sh runs the echo and grep commands that awk prints&lt;br /&gt;
#&amp;gt; pipes the output to a file&lt;br /&gt;
&lt;br /&gt;
===Converting IP abbreviations to CIDR===&lt;br /&gt;
in Apache directives you might block a range of IP addresses with an abbreviated domain like 198.183 , meaning all the addresses between 198.183.0.0 and 198.183.255.255 . My block lists used to contain such abbreviations, but also CIDR addresses, such as 198.182.0.0/16, which blocks the range 198.182.0.0 to 198.182.255.255 . CIDR is useful because we can block not just 256 or 65536 addresses, but any power of two. For example, we can block 198.184.0.0 to 198.184.16.255 with this CIDR-formatted address: 198.184.0.0/20. Internet addresses are allotted in large swaths to regional authorities, who then allot smaller parts to internet providers, who may even break it down into smaller lots. Most of these lots can be addressed with a single CIDR address.&lt;br /&gt;
&lt;br /&gt;
To convert an abbreviated two or three byte address to the full CIDR notation, use these handy regular expressions and replacements. Please note that there are spaces before and after the regular expressions as well as the replacements, to prevent converting partial addresses:&lt;br /&gt;
;Convert two-byte addresses&lt;br /&gt;
:The parentheses mark the group to be captured, in between spaces—Two sets of any number (+) of numerical digits ([0-9]) separated by a period (the backslash lets the regex engine know we want a period, not the special meaning of period in regex). Whatever was in parentheses will be returned by $1, followed by .0.0/16, which indicates the full range of possibilities in those two digits. We put 16 because the first 16 bits, of the range of 32-bit addresses, are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+) &lt;br /&gt;
  $1.0.0/16 &lt;br /&gt;
;Convert three-byte addresses&lt;br /&gt;
:Here, the first 24 bits are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+\.[0-9]+) &lt;br /&gt;
  $1.0/24 &lt;br /&gt;
;Convert four-byte (complete) addresses&lt;br /&gt;
:Here, all 32 bits are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) &lt;br /&gt;
  $1/32&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
[[Javascript recipes]]&lt;br /&gt;
&lt;br /&gt;
[[Serving web pages]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Webmaster_recipes&amp;diff=2913</id>
		<title>Webmaster recipes</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Webmaster_recipes&amp;diff=2913"/>
		<updated>2025-03-16T02:21:19Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Added logs one-liners&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Detect heavy users in logs===&lt;br /&gt;
 cat access.log | cut -d&amp;quot; &amp;quot; -f1|sort | uniq -c | sort -r|head&lt;br /&gt;
===Count access to each file, ignoring URL parameters===&lt;br /&gt;
 cat access.log |cut -d&amp;quot; &amp;quot; -f7|cut -d&amp;quot;?&amp;quot; -f1|sort|uniq -c&lt;br /&gt;
===Count access from an IP prefix===&lt;br /&gt;
 grep -c &amp;quot;^xxx.xxx.&amp;quot; access.log&lt;br /&gt;
===Dealing with hotlinking===&lt;br /&gt;
Hot-linking is the use of links to content at one site, usually images, by pages on another site. At first, page-designers may have used links to images on other sites because they couldn&#039;t create useful images themselves. These days, robots are made to make pages with random content, using both content and images from around the world to create a site in the hopes of fooling search engines into thinking that the site contains useful information on specific topics.&lt;br /&gt;
&lt;br /&gt;
====Searching logs for hotlinkers====&lt;br /&gt;
 awk &#039;{if ($7 !~ /\.(jpe?g|gif|png)$/) next;&lt;br /&gt;
 if ($11 ~ /^&amp;quot;https?:\/\/[^\/]*energyteachers.org/) next;&lt;br /&gt;
 if ($11 ~ /&amp;quot;-&amp;quot;/) next;&lt;br /&gt;
 print $11;}&#039; access_log* |sort|uniq -c|sort&lt;br /&gt;
;Explanation&lt;br /&gt;
*$7 refers to the seventh segment of the log, split by spaces, which contains the request.&lt;br /&gt;
*!~ means &amp;quot;does not contain the following expression&amp;quot;&lt;br /&gt;
*The expression between the slashes finds text that include a dot followed by one of the image extensions. The dollar sign signifies the end of the request.&lt;br /&gt;
*So, the first line of if...next tell awk to skip lines that aren&#039;t requests for image files.&lt;br /&gt;
*The second line skips references from energyteachers.org&lt;br /&gt;
*The third line skips empty references, allowing people to bookmark images or type their addresses in their browser.&lt;br /&gt;
*The fourth line prints the reference, and after finishing the awk command set, contains the wildcard-appended log-file-name to be processed, followed by a sort, then a count of how many times that reference was used, then sorting by that count.&lt;br /&gt;
&lt;br /&gt;
====Preventing hot-linking of images====&lt;br /&gt;
&lt;br /&gt;
There are hundreds of pages telling how to turn away hot-linkers using Apache&#039;s Rewrite module, but Apache suggests you use their built-in directives when possible, and this is one of those cases. So, I found a different way, thanks to the [http://wiki.apache.org/httpd/DisableImageHotLinking wiki] at apache.org.&lt;br /&gt;
 SetEnvIfNoCase Referer &amp;quot;^https?://([^/]*)?shawnreeves\.net/&amp;quot; local_ref=1&lt;br /&gt;
 SetEnvIf Referer ^$ local_ref=1&lt;br /&gt;
 &amp;lt;FilesMatch &amp;quot;\.(jpe?g|gif|png)$&amp;quot;&amp;gt;&lt;br /&gt;
  Order Allow,Deny&lt;br /&gt;
  Allow from env=local_ref&lt;br /&gt;
 &amp;lt;/FilesMatch&amp;gt;&lt;br /&gt;
#The first line uses a regular expression to match referrers that begin with http, with an optional s, followed by ://, then any number of non-slash characters, then the allowed domain (note the backslash to escape the period which normally is a wildcard). If the match is true, then an environmental variable local_ref is set to 1.&lt;br /&gt;
#The second line sets the local_ref variable to 1 if there is no referrer, such as when someone browses at an image from a bookmark or uses curl or some special tool for the blind.&lt;br /&gt;
#The third through sixth lines apply only if the files requested have image-type extensions.&lt;br /&gt;
#The fifth line allows such requests from anyone with the proper reference, leaving the rest to be denied by the order of the fourth line.&lt;br /&gt;
&lt;br /&gt;
===Multiple whois lookups===&lt;br /&gt;
I recently launched a new project at EnergyTeachers.org, [http://energyteachers.org/greendollhousechallenge.php Green Dollhouse Challenge], and I wanted to see who responded to a group email I posted about it. I downloaded the logs and retrieved the list of IP addresses that accessed the page with this command which searches for the word dollhouse in the server&#039;s log, taking just the first section which is the IP address, then sorting which is required for uniq, then listing only unique addresses with a count of how many visits came from each address:&lt;br /&gt;
 grep dollhouse access_log.2011-03-29|cut -d &amp;quot; &amp;quot; -f1| sort|uniq -c&lt;br /&gt;
I was taking each resulting IP and copying and pasting it after typing whois in another shell to find clues to whether the visitor was a search spider or a real person. I learned (from http://www.tek-tips.com/viewthread.cfm?qid=1566237&amp;amp;page=7 ) that I could use an inline text editor to type &amp;quot;whois &amp;quot; and the result from the above command, without the count, and then pass that to a shell within this shell to process each line as a command:&lt;br /&gt;
 grep dollhouse access_log.2011-03-29 | cut -d &amp;quot; &amp;quot; -f1&lt;br /&gt;
 | sort | uniq | awk &#039;{print &amp;quot;whois &amp;quot; $1}&#039; | sh&lt;br /&gt;
awk takes each line, prepends &amp;quot;whois &amp;quot;, and then sends it to the shell &amp;quot;sh&amp;quot; to process.&lt;br /&gt;
===Search queries===&lt;br /&gt;
Open a terminal and go to a directory full of Apache log files. Enter the following command (all on one line):&lt;br /&gt;
 egrep -r -h -o &amp;quot;.*q=[^&amp;amp;]*&amp;quot; ./*&lt;br /&gt;
 |awk &#039;{print $1&amp;quot;\t&amp;quot;substr($11,match($11,&amp;quot;q=&amp;quot;)+2)}&#039;&lt;br /&gt;
 |php -R &#039;echo substr(urldecode($argn),stripos($argn,&amp;quot;&amp;amp;&amp;quot;)).&amp;quot;\n&amp;quot;;&#039;&lt;br /&gt;
 &amp;gt; ../SearchQueriesIP.txt&lt;br /&gt;
Egrep will go through all the files in the folder (-r and ./*); find strings that have q= up to the next ampersand, which is usually how a search engine reports the query string that someone entered before they clicked on a result to get to our site; only output the matching part (-o); and skip listing the filename from the match (-h).&lt;br /&gt;
&lt;br /&gt;
Next, awk picks the IP address of the visitor ($1), a tab (\t), and then the query string ($11), leaving out the first two characters (q=). PHP then takes each line ($argn) and decodes the text, changing plus signs to spaces and so on. It also removes any unexplained extra bits following ampersands; this will become unnecessary when I figure out how some ampersands are slipping through.&lt;br /&gt;
&lt;br /&gt;
Finally, the results are saved to a file using the redirect symbol (&amp;gt;), in the next directory up (../) so egrep doesn&#039;t search its own output.&lt;br /&gt;
&lt;br /&gt;
====Issues with this analysis====&lt;br /&gt;
;q= might be in the request:If the request string includes the string q=, then this would return that request instead of the referrer&#039;s query. A solution may be to use awk instead of grep, only checking the 11th field.&lt;br /&gt;
;Analysis of requests:This doesn&#039;t output or process the request field. Easy enough to fix, we could just add field $7 to the print command in awk, or some significant substring of $9.&lt;br /&gt;
&lt;br /&gt;
It&#039;s a little sad to see so many people type energyteachers.org into google instead of directly into the address area of the browser. I guess Google has no problem being seen as the gateway to the internet, even with the futile bandwidth usage.&lt;br /&gt;
&lt;br /&gt;
====Better performing with awk====&lt;br /&gt;
Here&#039;s a more awkward process, but it only has one pipe.&lt;br /&gt;
 awk &#039;{if ($11 !~ /q=/) next;&lt;br /&gt;
 split($11,queries,&amp;quot;=&amp;quot;);&lt;br /&gt;
 for (var in queries) if (match(queries[var],/q$/)) searched=queries[var+1];&lt;br /&gt;
 print $1&amp;quot;\t&amp;quot;$7&amp;quot;\t&amp;quot;substr(searched,1,match(searched,&amp;quot;&amp;amp;&amp;quot;)-1)}&#039; access_log*&lt;br /&gt;
 |php -R &#039;echo urldecode($argn).&amp;quot;\n&amp;quot;;&#039;&lt;br /&gt;
The first line skips input lines that don&#039;t have &amp;quot;q=&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The second line splits the referrer line by equal signs, essentially separating fields, into an array &amp;quot;queries&amp;quot;. The third line looks for the item in queries that ends with q, setting our target to the next item in the array, since it must follow &amp;quot;q=&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The fourth line prints the IP address of the requester, the page requested, and search query. The fifth line takes each line ($argn) and decodes the text, changing plus signs to spaces and so on.&lt;br /&gt;
===Popularity of a page over time===&lt;br /&gt;
 awk &#039;$1 !~&amp;quot;MY_WORK_IP&amp;quot; &amp;amp;&amp;amp; $7 ~ /PAGE_NAME/ \&lt;br /&gt;
 {print substr($4,5,3)&amp;quot; &amp;quot;substr($4,2,2)}&#039; access* |uniq -c&lt;br /&gt;
This script skips all requests from my own IP, so I don&#039;t count my own hits, includes all requests for a certain PAGE_NAME or subset of pages with a certain text in their name, and returns the month and date, then counts how many hits there are each date. Note the backslash at the end of the first line is not part of the awk script but just a way to split this shell command into two lines. I.e., if you use it on one line, remove the backslash.&lt;br /&gt;
===Track logs according to hit===&lt;br /&gt;
Sometimes I want to see what people do when after or before they hit a certain page. With the following line, broken into readable chunks by back-slashes, of shell commands, I can search Apache logs to see the activity of anyone who hits a given page.&lt;br /&gt;
 grep -rh &amp;quot;GET /ENTRY_PAGE_EXAMPLE&amp;quot; . | \&lt;br /&gt;
 cut -d &amp;quot; &amp;quot; -f 1| \&lt;br /&gt;
 sort|uniq| \&lt;br /&gt;
 awk &#039;{print &amp;quot;echo &amp;quot;$1&amp;quot;;grep -rh &amp;quot; $1&amp;quot; \.&amp;quot;}&#039; | \&lt;br /&gt;
 sh&amp;gt;../ENTRY_PAGE_EXAMPLE-viewers.txt&lt;br /&gt;
#Grep searches all files in the current directory for a request for whatever page.&lt;br /&gt;
#Cut selects just the first item, which should be the IP address of the browser.&lt;br /&gt;
#Sort and uniq pass just one copy of each IP address that comes through.&lt;br /&gt;
#Awk creates a command to print a list of accesses from each IP address.&lt;br /&gt;
##Echo will print the IP address on a line, as a header to help readability.&lt;br /&gt;
##Grep will find all occurrences of each IP address.&lt;br /&gt;
#Sh runs the echo and grep commands that awk prints&lt;br /&gt;
#&amp;gt; pipes the output to a file&lt;br /&gt;
&lt;br /&gt;
===Converting IP abbreviations to CIDR===&lt;br /&gt;
in Apache directives you might block a range of IP addresses with an abbreviated domain like 198.183 , meaning all the addresses between 198.183.0.0 and 198.183.255.255 . My block lists used to contain such abbreviations, but also CIDR addresses, such as 198.182.0.0/16, which blocks the range 198.182.0.0 to 198.182.255.255 . CIDR is useful because we can block not just 256 or 65536 addresses, but any power of two. For example, we can block 198.184.0.0 to 198.184.16.255 with this CIDR-formatted address: 198.184.0.0/20. Internet addresses are allotted in large swaths to regional authorities, who then allot smaller parts to internet providers, who may even break it down into smaller lots. Most of these lots can be addressed with a single CIDR address.&lt;br /&gt;
&lt;br /&gt;
To convert an abbreviated two or three byte address to the full CIDR notation, use these handy regular expressions and replacements. Please note that there are spaces before and after the regular expressions as well as the replacements, to prevent converting partial addresses:&lt;br /&gt;
;Convert two-byte addresses&lt;br /&gt;
:The parentheses mark the group to be captured, in between spaces—Two sets of any number (+) of numerical digits ([0-9]) separated by a period (the backslash lets the regex engine know we want a period, not the special meaning of period in regex). Whatever was in parentheses will be returned by $1, followed by .0.0/16, which indicates the full range of possibilities in those two digits. We put 16 because the first 16 bits, of the range of 32-bit addresses, are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+) &lt;br /&gt;
  $1.0.0/16 &lt;br /&gt;
;Convert three-byte addresses&lt;br /&gt;
:Here, the first 24 bits are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+\.[0-9]+) &lt;br /&gt;
  $1.0/24 &lt;br /&gt;
;Convert four-byte (complete) addresses&lt;br /&gt;
:Here, all 32 bits are constant.&lt;br /&gt;
&#039;&#039;&#039;WARNING: IF COPYING, DON&amp;quot;T FORGET THE SPACES, ESPECIALLY AT THE END OF EACH EXPRESSION!&#039;&#039;&#039;&lt;br /&gt;
  ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) &lt;br /&gt;
  $1/32&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
[[Javascript recipes]]&lt;br /&gt;
&lt;br /&gt;
[[Serving web pages]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Computers]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2912</id>
		<title>Apple Music and iTunes how-to</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2912"/>
		<updated>2024-11-13T19:28:04Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Playlists */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Playlists ==&lt;br /&gt;
=== How to get a Smart Playlist to display only rated tunes ===&lt;br /&gt;
[[File:Smart Playlist includes unrated tunes.png|thumb|right|Showing how unrated tunes from rated albums show in Smart Playlist based on rating.]]&lt;br /&gt;
If some unrated tunes are showing in a Smart Playlist with a rule for matching rated tunes, it is because the album is also rated. For example, if a playlist is set to include only tunes with a rating of four, it will include all songs from albums which are rated four.&lt;br /&gt;
&lt;br /&gt;
The fix is to unrate the album, which will not change the ratings of individually rated songs. When you find unrated items in your playlist, click on their disclosure dots ..., select &amp;quot;Show in Album&amp;quot;, click on the album&#039;s disclosure dots, then Rating, then None.&lt;br /&gt;
[[Category:Computers]][[Category:How-to]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2911</id>
		<title>Apple Music and iTunes how-to</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2911"/>
		<updated>2024-11-13T19:25:06Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* How to get a Smart Playlist to display only rated tunes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Playlists ==&lt;br /&gt;
=== How to get a Smart Playlist to display only rated tunes ===&lt;br /&gt;
[[File:Smart Playlist includes unrated tunes.png|thumb|right|Showing how unrated tunes from rated albums show in Smart Playlist based on rating.]]&lt;br /&gt;
If some unrated tunes are showing in a Smart Playlist with a rule for matching rated tunes, it is because the album is also rated. For example, if a playlist is set to include only tunes with a rating of four, it will include all songs from albums which are rated four.&lt;br /&gt;
&lt;br /&gt;
The fix is to unrate the album, which will not change the ratings of individually rated songs.&lt;br /&gt;
[[Category:Computers]][[Category:How-to]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2910</id>
		<title>Apple Music and iTunes how-to</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Apple_Music_and_iTunes_how-to&amp;diff=2910"/>
		<updated>2024-11-13T19:24:43Z</updated>

		<summary type="html">&lt;p&gt;Shawn: New page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Playlists ==&lt;br /&gt;
=== How to get a Smart Playlist to display only rated tunes ===&lt;br /&gt;
[[File:Smart Playlist includes unrated tunes.png|thumb|right|Showing how unrated tunes from rated albums show in Smart Playlist based on rating.]]&lt;br /&gt;
If some unrated tunes are showing in a Smart Playlist with a rule for matching rated tunes, it is because the album is also rated. For example, if a playlist is set to include only tunes with a rating of four, it will include all songs from albums which are rated four. The fix is to unrate the album, which will not change the ratings of individually rated songs.&lt;br /&gt;
[[Category:Computers]][[Category:How-to]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=File:Smart_Playlist_includes_unrated_tunes.png&amp;diff=2909</id>
		<title>File:Smart Playlist includes unrated tunes.png</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=File:Smart_Playlist_includes_unrated_tunes.png&amp;diff=2909"/>
		<updated>2024-11-13T19:23:16Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Showing how a Smart Playlist in Music/iTunes shows unrated tunes if the album is rated.&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Distance_grapher&amp;diff=2908</id>
		<title>Distance grapher</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Distance_grapher&amp;diff=2908"/>
		<updated>2024-06-16T22:09:53Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Categorizing in PT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Arduino and HC-SR04 distance grapher ==&lt;br /&gt;
We use any Arduino connected to a computer running the Arduino Integrated Development Environment, and an HC-SR04, a very inexpensive ultrasonic distance sensor.&lt;br /&gt;
The program periodically sends a trigger signal to the sensor, which in turn emits a series of eight blips in ultrasonic sound. The sensor listens for the blips to return, all the while keeping the &amp;quot;echo&amp;quot; signal pin high. Meanwhile, as soon as the trigger signal is sent, the Arduino keeps track of how long the echo signal pin is high. When the echo signal pin returns to low, the Arduino calculates how long the time of flight was, divides by two, and multiplies by the speed of sound to get the distance measured.&lt;br /&gt;
&lt;br /&gt;
=== Circuit ===&lt;br /&gt;
It&#039;s always smart to make connections while Arduino is not powered, connected to USB or otherwise. You can choose any input-output pin, but avoid the ones labeled RX and TX, 0 and 1, if you are using UNO or similar non-native-USB board. Here we use 4 and 5.&lt;br /&gt;
Arduino label &amp;lt;&amp;gt; HC-SR04 label:&lt;br /&gt;
* GND &amp;lt;&amp;gt; GND&lt;br /&gt;
* 5V &amp;lt;&amp;gt; VCC&lt;br /&gt;
* 4 &amp;lt;&amp;gt; TRIG&lt;br /&gt;
* 5 &amp;lt;&amp;gt; ECHO&lt;br /&gt;
&lt;br /&gt;
=== Arduino code ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
const int soundMicrosecondsPerCentimeter = 29;&lt;br /&gt;
const int TRIG = 3;&lt;br /&gt;
const int ECHO = 5;&lt;br /&gt;
const unsigned long measurementPeriod = 100;//ms&lt;br /&gt;
unsigned long lastMeasurementTime = 0;&lt;br /&gt;
long duration, cm;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // initialize serial communication:&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  pinMode(ECHO, INPUT);&lt;br /&gt;
  pinMode(TRIG, OUTPUT);&lt;br /&gt;
  digitalWrite(TRIG, LOW);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if(millis()-lastMeasurementTime &amp;gt; measurementPeriod){&lt;br /&gt;
    lastMeasurementTime = millis();&lt;br /&gt;
    digitalWrite(TRIG, LOW);&lt;br /&gt;
    delayMicroseconds(2);&lt;br /&gt;
    digitalWrite(TRIG, HIGH);&lt;br /&gt;
    delayMicroseconds(10);&lt;br /&gt;
    digitalWrite(TRIG, LOW);&lt;br /&gt;
    duration = pulseIn(ECHO, HIGH);&lt;br /&gt;
    cm = duration/soundMicrosecondsPerCentimeter/2;&lt;br /&gt;
    Serial.print(cm);&lt;br /&gt;
    Serial.println(&amp;quot;cm&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Graphing ===&lt;br /&gt;
Once the circuit is set up, the HC-SR04 is pointing where you want it, the Arduino is connected to power, and the code is uploaded to the Arduino, turn on &amp;quot;Serial Plotter&amp;quot; from the Tools menu of the Arduino IDE. It will plot numbers it sees coming in the same serial port used to upload the code. Be sure the baud rate in Serial Plotter matches that in the code.&lt;br /&gt;
&lt;br /&gt;
[[Category:Physics teaching]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Distance_grapher&amp;diff=2907</id>
		<title>Distance grapher</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Distance_grapher&amp;diff=2907"/>
		<updated>2024-06-16T22:07:19Z</updated>

		<summary type="html">&lt;p&gt;Shawn: Created page with &amp;quot;== Arduino and HC-SR04 distance grapher == We use any Arduino connected to a computer running the Arduino Integrated Development Environment, and an HC-SR04, a very inexpensiv...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Arduino and HC-SR04 distance grapher ==&lt;br /&gt;
We use any Arduino connected to a computer running the Arduino Integrated Development Environment, and an HC-SR04, a very inexpensive ultrasonic distance sensor.&lt;br /&gt;
The program periodically sends a trigger signal to the sensor, which in turn emits a series of eight blips in ultrasonic sound. The sensor listens for the blips to return, all the while keeping the &amp;quot;echo&amp;quot; signal pin high. Meanwhile, as soon as the trigger signal is sent, the Arduino keeps track of how long the echo signal pin is high. When the echo signal pin returns to low, the Arduino calculates how long the time of flight was, divides by two, and multiplies by the speed of sound to get the distance measured.&lt;br /&gt;
&lt;br /&gt;
=== Circuit ===&lt;br /&gt;
It&#039;s always smart to make connections while Arduino is not powered, connected to USB or otherwise. You can choose any input-output pin, but avoid the ones labeled RX and TX, 0 and 1, if you are using UNO or similar non-native-USB board. Here we use 4 and 5.&lt;br /&gt;
Arduino label &amp;lt;&amp;gt; HC-SR04 label:&lt;br /&gt;
* GND &amp;lt;&amp;gt; GND&lt;br /&gt;
* 5V &amp;lt;&amp;gt; VCC&lt;br /&gt;
* 4 &amp;lt;&amp;gt; TRIG&lt;br /&gt;
* 5 &amp;lt;&amp;gt; ECHO&lt;br /&gt;
&lt;br /&gt;
=== Arduino code ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
const int soundMicrosecondsPerCentimeter = 29;&lt;br /&gt;
const int TRIG = 3;&lt;br /&gt;
const int ECHO = 5;&lt;br /&gt;
const unsigned long measurementPeriod = 100;//ms&lt;br /&gt;
unsigned long lastMeasurementTime = 0;&lt;br /&gt;
long duration, cm;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // initialize serial communication:&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  pinMode(ECHO, INPUT);&lt;br /&gt;
  pinMode(TRIG, OUTPUT);&lt;br /&gt;
  digitalWrite(TRIG, LOW);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if(millis()-lastMeasurementTime &amp;gt; measurementPeriod){&lt;br /&gt;
    lastMeasurementTime = millis();&lt;br /&gt;
    digitalWrite(TRIG, LOW);&lt;br /&gt;
    delayMicroseconds(2);&lt;br /&gt;
    digitalWrite(TRIG, HIGH);&lt;br /&gt;
    delayMicroseconds(10);&lt;br /&gt;
    digitalWrite(TRIG, LOW);&lt;br /&gt;
    duration = pulseIn(ECHO, HIGH);&lt;br /&gt;
    cm = duration/soundMicrosecondsPerCentimeter/2;&lt;br /&gt;
    Serial.print(cm);&lt;br /&gt;
    Serial.println(&amp;quot;cm&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Graphing ===&lt;br /&gt;
Once the circuit is set up, the HC-SR04 is pointing where you want it, the Arduino is connected to power, and the code is uploaded to the Arduino, turn on &amp;quot;Serial Plotter&amp;quot; from the Tools menu of the Arduino IDE. It will plot numbers it sees coming in the same serial port used to upload the code. Be sure the baud rate in Serial Plotter matches that in the code.&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2906</id>
		<title>Circuits for teaching physics</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2906"/>
		<updated>2024-06-16T21:30:17Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Example circuits */ Added Data-graphing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Rationale===&lt;br /&gt;
I&#039;ve taught my students to build electronic circuits, and, separately, I&#039;ve taught my students to devise their own experimental apparatus. While these two movements in my teaching have been two of the most successful, I&#039;ve yet to successfully combine them, yet to ask them to build their own circuits as lab apparatus for studying something else. It&#039;s so promising that I&#039;ve decided to ask others to join me in the trial.&lt;br /&gt;
&lt;br /&gt;
Having our physics students build their own apparatus might have multiple benefits:&lt;br /&gt;
#Affordability&lt;br /&gt;
##Save schools that would otherwise buy commercial apparatus a large fraction of the cost.&lt;br /&gt;
##Allow schools that would otherwise miss out because they couldn&#039;t afford the commercial apparatus.&lt;br /&gt;
##Allow more students of more schools to borrow lab equipment for homework, or even have more students own their lab equipment outright.&lt;br /&gt;
#Pedagogical benefits&lt;br /&gt;
##We hope to increase student ownership of the process of learning in the laboratory. Students may be more interested in the measurement of a physical variable when they have created the apparatus.&lt;br /&gt;
##Allow students to learn a skill to be used in other environments, including students who would not elect to learn circuits or programming, but would elect physics.&lt;br /&gt;
##Attract students interested in circuits and programming to physics.&lt;br /&gt;
#Curriculum&lt;br /&gt;
##Learning about identifying resistors and what makes appropriate substitutions helps students understand why orders of magnitude are an important way of making comparisons. After they&#039;ve started to learn the resistor color code, I ask my students which color-band is the most important, i.e. getting which one wrong would most likely affect the operation of the circuit.&lt;br /&gt;
##Specifying or substituting components, for example choosing among diodes or transistors, should help a student learn about the physical characteristics of those components.&lt;br /&gt;
##Students should be less iffy about the nature of electrical connections than students who study physics without building circuits.&lt;br /&gt;
&lt;br /&gt;
===Learning physics with circuits===&lt;br /&gt;
What will students learn about physics with circuits they build?&lt;br /&gt;
&lt;br /&gt;
Traditionally, physics students learn about circuits as a topic of physics after learning about electricity and magnetism. Instead, here I am suggesting we teach students about circuits as tools for learning in a wider range of fields of physics, from mechanics to astronomy, with rich opportunities to learn the traditional things about circuits scattered along the way.&lt;br /&gt;
&lt;br /&gt;
So, to start, students could be expected to learn about the traditional topics in circuits, such as resistance, capacitance, induction, EMF, parallel and series combinations, amplification, and various more advanced topics.&lt;br /&gt;
&lt;br /&gt;
But &#039;&#039;using&#039;&#039; circuits they can investigate waves, interference, optics, kinematics, dynamics, electric and magnetic fields, energy transfers, thermodynamics, the spectrum, and more.&lt;br /&gt;
&lt;br /&gt;
In February, 2014, I took a poll of teachers in the Syracuse area, asking which circuits, from a list I thought might be easy yet useful, they&#039;d most like to make in a workshop to take to their schools. The following table of results shows how important photo-gates are to physics teachers. One could argue that volt-meters are so popular that they&#039;re universally already-owned. Or, one could argue that they are not popular because they are used for studying electricity, not as canonical a topic as the kinematics studied with the photo-gates.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! circuit!! votes&lt;br /&gt;
|-&lt;br /&gt;
| photogates-timer || 12&lt;br /&gt;
|-&lt;br /&gt;
| anemometer || 8&lt;br /&gt;
|-&lt;br /&gt;
| wheel-speedometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| magnetometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| ammeter || 4&lt;br /&gt;
|-&lt;br /&gt;
| digital-thermometer || 4&lt;br /&gt;
|-&lt;br /&gt;
| light-meter || 3&lt;br /&gt;
|-&lt;br /&gt;
| data-logger || 3&lt;br /&gt;
|-&lt;br /&gt;
| volt-meter || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some circuits use only discrete components, many use integrated circuits like the 555 timer or the 741 op amp, and some use micro-controllers to gather data or run a complex algorithm or interface.&lt;br /&gt;
&lt;br /&gt;
The micro-controller requires special consideration, because each unit, be it a chip or a board, can cost anywhere between $1 and $40. With the right programming-circuit and software, a $2 chip can be programmed as easily as a $10 chip, and may be versatile enough to do what some are doing with their $30 boards.&lt;br /&gt;
&lt;br /&gt;
===Sensors===&lt;br /&gt;
There is a multitude of sensors that can be connected to processors or directly to outputs. Sensors can be used to study the physical phenomena sensed, but they also can be used to teach the different ways of processing their signals.&lt;br /&gt;
&lt;br /&gt;
====Analog sensors====&lt;br /&gt;
;Humidity sensors:Humidity sensors may output relative or absolute humidity values, and are often packaged with a temperature sensor so we can convert to the other value through software.&lt;br /&gt;
;Light-dependent resistors:LDRs are usually cadmium sulfide, which changes resistance according to how much light is falling on the cell. Cadmium is a toxic metal, so we usually use non-toxic alternatives like photo-transistors or photo-diodes or solar cells, especially for children&#039;s use. They react to changes in light more slowly than diodes and transistors, but they are easy to model as predictable, variable resistors.&lt;br /&gt;
;Potentiometers and rheostats:Variable resistors are usually a knob or a slider that change resistance from zero to some given value. Some, marked α (alpha) or A, are logarithmically tapered so that they can control audio or light over a wide, exponential range of values. Linear variable resistors are marked β (beta) or B.&lt;br /&gt;
;Thermistors:Temperature-dependent resistors may have a negative or positive temperature coefficient, according to whether their resistance goes down or up when their temperature goes up. See wikipedia for more information, including a discussion of how they can increase temperature because the circuit is adding energy via the current used to sense its resistance. http://en.wikipedia.org/wiki/Thermistor&lt;br /&gt;
;Thermopiles:Thermopiles are semiconductor devices that change resistance or voltage in a circuit depending on their temperature, and they are thermally shielded so that they rise and fall in temperature with remote objects they face through a window in their otherwise heavy insulation. The window is usually made of a material that doesn&#039;t allow visible light, so that it is tuned to sensing temperatures corresponding to a peak wavelength in far infrared. These are the sensors used for non-contact thermometers, like those medical personnel use to take a person&#039;s temperature via ear or mouth.&lt;br /&gt;
====On-off sensors====&lt;br /&gt;
;Passive infrared motion detectors:PIR devices often output a voltage between their supply and 1.5V when not detecting changing infrared light, then short their output to ground when they do detect changing infrared light. When using such PIR detectors with a micro-controller or similar logic ICs, pull the output up with a resistor, which may be an internal feature in micro-controllers like the Arduino, so that the output is clearly high or low.&lt;br /&gt;
;Switches:Switches can be purchased or hand-made from all sorts of materials, like chewing-gum wrappers. A multitude of types of switches can be salvaged from old electronic equipment, like remote controls, tape players, and phones. They connect one or more conduits to one or more other conduits, and may make the connection when pushed, or disconnect when pushed, or toggle between connected and disconnected when pushed and released. They may spring back to a default position or they may stay in any state.&lt;br /&gt;
;Tilt switches:These switches consist of a metal ball or mercury that makes contact only when it is tilted a certain amount. This is how mercury thermostats work.&lt;br /&gt;
;Ultrasonic distance sensors:These sensors send a train of ultrasonic pings when their trigger pin is taken high or low, then set an echo pin high or low for the duration of the flight of the pings to a reflecting object and back.&lt;br /&gt;
;Vibration switches:These switches consist of a stiff wire surrounded by a metal coil that only contacts the wire when shaken.&lt;br /&gt;
&lt;br /&gt;
====Digital-value sensors====&lt;br /&gt;
&lt;br /&gt;
====Commercial sensors====&lt;br /&gt;
There are ways to connect sensors from commercial systems, the most well-known companies being Vernier and PASCO, to circuits—Some sensors output analog values on one wire when powered on two others, while some speak a digital code that may be open to the public. For example, Vernier publishes a guide to connecting their sensors to the Arduino. &amp;lt;ref&amp;gt;http://www.vernier.com/engineering/arduino/&amp;lt;/ref&amp;gt; PASCO explains how the wires on various sensors function.&amp;lt;ref&amp;gt;http://www.pasco.com/support/technical-support/technote/techIDlookup.cfm?TechNoteID=436&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Outputs===&lt;br /&gt;
See [[#Display]] for a discussion of displaying characters.&lt;br /&gt;
====Sound transducers====&lt;br /&gt;
;Speakers:Circuits can vibrate a speaker to make sound, and the pitch, timbre, and/or volume can indicate criteria.&lt;br /&gt;
;Piezo buzzers:Piezo buzzers buzz a certain tone with an applied voltage, but can be made to make more interesting sounds.&lt;br /&gt;
;Piezo elements:Piezo elements click when the voltage applied goes over some threshold, and the clicking can be very fast, so one may make square waves of many frequencies with them.&lt;br /&gt;
====Light transducers====&lt;br /&gt;
All the following transducers may be arranged in character or graphical displays, including light bars, bar graphs, multi-dimensional arrays, and two-dimensional screens.&lt;br /&gt;
;Light emitting diodes:LEDs usually convert a specific voltage to a narrow band of light with a frequency correlated to that voltage. i.e., blue LEDs operate at a higher voltage than red LEDs. LEDs can turn on and off extremely quickly, so dimming is usually handled by running them with a square wave of varying duty cycle. When they&#039;re not busy emitting, LEDs can also be used as photodiodes to detect light levels.&lt;br /&gt;
;Incandescent lamps:Incandescent lamps can be had over a wide range of voltages, and their brightness and color depend on the voltage applied.&lt;br /&gt;
;Plasma lamps:Plasma lamps, for instance neon bulbs, require high voltages to light, but can be visible with very little current.&lt;br /&gt;
;Liquid crystal display:LCDs typically use minuscule amounts of power compared to other ways of displaying characters or graphics. At around $10 per display, they are an inexpensive and efficient way to display a short line or two of text. While many displays are proprietary, there are also many with common protocols that allow easy control.&lt;br /&gt;
====Relays====&lt;br /&gt;
Relays are switches controlled by current, for instance allowing a 5-volt DC system to control a 110-volt AC system without any electrical connection between the two systems.&lt;br /&gt;
;Magnetic relay:Magnetic relays are the switches you may hear in the car when you turn on or off a device, for example when a low-current line to a switch on the dashboard switches a high-current line through the headlights.&lt;br /&gt;
;Solid state relay:SSRs rely on semiconductor properties to allow a small current to light an LED which controls a photo-transistor or light-activated silicon-controlled rectifier (LASCR), thus electrically isolating the two systems through light. They can be ten times the cost of magnetic relays, but can last much longer and act much more quickly.&lt;br /&gt;
&lt;br /&gt;
===Example circuits===&lt;br /&gt;
====Photo-gate timer====&lt;br /&gt;
A photo-gate timer uses light emitters and receivers to detect the passage of an object. The simplest timer would be a single light receiver, such as a photodiode or light-dependent resistor, that darkens when the leading edge of an object passes over it and lightens when that object&#039;s trailing edge passes over it. A circuit could be made to count beats of a clock between the two events. Then, for example, the known length of the object could be divided by the time between the two events to determine the average velocity of the object through the gate.&lt;br /&gt;
&lt;br /&gt;
A more commonly used system in the teaching laboratory is a set of two gates, where the source is not the ambient light but a light-emitting diode (LED) paired with a photodiode designed to be sensitive to the color of the LED, that color usually being infrared. Each gate is triggered when the leading edge of the object first blocks the light. By only paying attention to the leading edge, the timing is independent of the geometry of the object and its shadow. By using infrared instead of visible light, spurious signals from visible light and shadow in the lab are removed, and the receiver does not have to be calibrated for laboratories of varying brightness. The disadvantage of infrared is it is harder to tell whether the emitter is operating—Keep an old cell-phone camera handy; because they lack an infrared filter, they can be used to check IR LEDs.&lt;br /&gt;
&lt;br /&gt;
It is possible to time events without micro-controllers or computers—Shading the first detector could lower voltage enough to trip a monostable 555 to reset a bank of counter ICs. The least-significant counter IC could be fed clock signals from an astable 555. The last detector could likewise disable counting.&lt;br /&gt;
&lt;br /&gt;
But, the complexity of watching multiple gates, ignoring spurious signals, counting time, and reporting that time to a display or computer, makes a micro-controller the best tool for the job.&lt;br /&gt;
&lt;br /&gt;
For an example, see [[photo-gate timer]].&lt;br /&gt;
&lt;br /&gt;
====Wheel-speedometer====&lt;br /&gt;
See [[bicycle speedometer]].&lt;br /&gt;
&lt;br /&gt;
Most speedometers are really rotational frequency-meters, with readings calculated according to the circumference of the spinning object. See [[frequency meter]].&lt;br /&gt;
&lt;br /&gt;
====Anemometer====&lt;br /&gt;
Exactly the same circuit as wheel speedometer, or may use a lookup table instead of a calculation if it does not have a linear response to wind speed.&lt;br /&gt;
&lt;br /&gt;
====Magnetometer====&lt;br /&gt;
Read values from a Hall-effect sensor or an integrated-chip, multi-axis magnetometer. See [[magnetometer]] for more discussion.&lt;br /&gt;
&lt;br /&gt;
====Light-to-sound====&lt;br /&gt;
The conductivity of a light-dependent resistor is proportional to the light falling on it. It can be placed in different parts of a 555-timer circuit to play a variable pitch through a speaker. https://energyteachers.org/project_detail.php?project_id=15&lt;br /&gt;
&lt;br /&gt;
====Ammeter====&lt;br /&gt;
The circuit design depends on whether measuring DC or AC current, and whether in contact or not with the measured circuit.&lt;br /&gt;
&lt;br /&gt;
====Thermometer====&lt;br /&gt;
Measure the voltage across a thermocouple, the resistance across a thermistor, or use an integrated-chip that responds with data to serial commands.&lt;br /&gt;
&lt;br /&gt;
====Light-meter====&lt;br /&gt;
Measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Light-polarization meter====&lt;br /&gt;
For each of two sensors behind two crossed polarizers, measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Data-logging====&lt;br /&gt;
Have the micro-controller write data from whatever input to a memory-chip, or internal memory if sufficient, for retrieval later.&lt;br /&gt;
&lt;br /&gt;
====Data-graphing====&lt;br /&gt;
Have the micro-controller write data from whatever input to a connected computer, for graphing. See [[Distance grapher]].&lt;br /&gt;
&lt;br /&gt;
====Voltmeter====&lt;br /&gt;
Measure the voltage between a pin and ground, using a divider when appropriate.&lt;br /&gt;
&lt;br /&gt;
===Micro-controllers===&lt;br /&gt;
There are thousands of integrated circuits that serve specific purposes, such as counting voltage drops on one pin and providing the count as binary on a set of other pins. Micro-controllers allow us to program a chip to serve a custom purpose, for comparison to the previous example, say counting voltage drops on one pin, comparing the period between the last two drops to the average of the last ten periods, to determine if something is slowing down or speeding up, then lighting a green or red LED accordingly. Micro-controllers allow us to customize them through programming, and most can be re-programmed many times, making them a versatile investment.&lt;br /&gt;
====Programming micro-controllers====&lt;br /&gt;
To learn your commands, they micro-controller must be told them, and there are very many ways this can happen, depending on the model of micro-controller. Here are some methods I&#039;ve used, with costs for comparison:&lt;br /&gt;
#Use PICAXE computer software (free) to write the commands in BASIC, compile it, and send it via serial cable ($10-20) to a PICAXE chip ($3-$10) in a programming circuit ($5), then put the chip in the working circuit.&lt;br /&gt;
#Use linux program MCU8051 (free) to write and compile a program in 8051 [http://en.wikipedia.org/wiki/Assembly_language assembly language], and send it via serial cable ($10-$20) to a parallel-eeprom programming board ($100) to an Atmel 89C2051 chip ($1).&lt;br /&gt;
#Use Arduino software (free) to write and compile a program in C and send it via serial or USB to an Arduino board ($10-$30) or an AVR micro-controller ($3-$5), on a breadboard ($5) with supporting components ($1), that has been loaded with the Arduino bootloader.&lt;br /&gt;
Many of these scenarios require only very minimal computers by today&#039;s standards. In fact, it&#039;s best to have an older computer (late 1990s, early 200s) that has built-in serial ports and can easily be outfitted with Linux.&lt;br /&gt;
&lt;br /&gt;
Learning to program micro-controllers is not completely unlike learning to program computers, and should be an enriching experience for students.&lt;br /&gt;
===Data-handling===&lt;br /&gt;
There are many ways to read measurements.&lt;br /&gt;
====Storage====&lt;br /&gt;
Some applications require data to be stored and retrieved later, such as in long-term anemometry or thermodynamic studies.&lt;br /&gt;
*A single count, such as in a timing application using pulses from a 555 IC, can be stored in a digital counter IC.&lt;br /&gt;
*Micro-controllers can store data in flash memory to be retrieved via a display or serial communications.&lt;br /&gt;
*Micro-controllers can write to disk drives, flash memory, or removable flash memory.&lt;br /&gt;
*A circuit can communicate with a computer via a serial connection.&lt;br /&gt;
====Display====&lt;br /&gt;
Digital circuits can have a numeric display.&lt;br /&gt;
*1-4 digits are best displayed by seven-segment LED displays, which can be directly driven by micro-controllers with at least 8 output pins, or driven by counter or driver ICs.&lt;br /&gt;
*More digits and/or text can be displayed by LCD displays ($10-$20).&lt;br /&gt;
*Many circuits can communicate with a computer to display and/or store readings, usually through a serial port.&lt;br /&gt;
*A voltmeter across two points of a circuit can be used with a lookup table to determine measurements.&lt;br /&gt;
&lt;br /&gt;
===Supporting apparatus===&lt;br /&gt;
Many laboratories will need equipment such as computers for programming micro-controllers or oscilloscopes for visualizing outputs of sensing circuits.&lt;br /&gt;
&lt;br /&gt;
====Power supplies====&lt;br /&gt;
There are many considerations when choosing power supplies&lt;br /&gt;
;Safety:Batteries are excellent for safety. One thing to watch out for is students putting two 9V batteries together, since their terminals almost beg to be put together. 9V batteries are also dangerous to store, having both terminals so close to each other, leading to inadvertent shorts.&lt;br /&gt;
;Economy:I use rechargeable batteries, which easily last through a school-day or through a unit, then go into a recharger.&lt;br /&gt;
;Voltage:Some components, like the rugged 555 timer IC, can take a wide range of voltages from supplies. Micro-controllers usually have much stricter operating ranges, and some are incompatible with others, two popular ranges being 4.5V-5.5V, and 3.0V-3.5V.&lt;br /&gt;
My students usually use a 2xAA, 3xAA, or 4xAAA battery pack or a 9V battery, all which connect to a breadboard with a standard 9V-style-terminated cable.&lt;br /&gt;
&lt;br /&gt;
====Solderless breadboards====&lt;br /&gt;
My students use and re-use versatile solderless breadboards. It takes a lesson for them to understand how it makes connections in circuits, and I&#039;ve found students of all ages over 9 are capable, after a few times practice, of understanding the difference between an abstract diagram and the actual placement of components on the breadboard.&lt;br /&gt;
====Tools for an electronics lab====&lt;br /&gt;
*Needle-nose pliers.&lt;br /&gt;
*Fine wire cutters.&lt;br /&gt;
*Chip pullers and inserters.&lt;br /&gt;
*Digital multimeters; measuring DCV, ACV, mA, A, Ω, and Hz, preferably.&lt;br /&gt;
*Transistor/diode tester (called &amp;quot;Component Tester&amp;quot; at Radio Shack).&lt;br /&gt;
*Oscilloscope.&lt;br /&gt;
&lt;br /&gt;
===Sample lessons===&lt;br /&gt;
Ask each student per pair to make a circuit that produces a tone that they expect to be harmonious with the other student&#039;s, then examine the two as X and Y components on an oscilloscope, enjoying the lissajous-figures associated with the harmonic pairs.&lt;br /&gt;
&lt;br /&gt;
Build a spectrometer with a solar cell and a stepper motor, then investigate spectra.&lt;br /&gt;
&lt;br /&gt;
Build a circuit to measure an unknown resistance by comparison with known resistances.&lt;br /&gt;
&lt;br /&gt;
===Teachers using circuits===&lt;br /&gt;
These educators have been kind enough to share their experiences using circuits to teach physics:&lt;br /&gt;
;Peter Siegel, California State Polytechnic University, Pomona:http://www.csupomona.edu/~pbsiegel/&lt;br /&gt;
;John Liu, St. Cloud State University, Minnesota:http://liudr.wordpress.com&lt;br /&gt;
;William Baird et al., Armstrong Atlantic State University, Savannah, Georgia:See their article &#039;&#039;The Light-Emitting Diode as a Light Detector&#039;&#039; in The Physics Teacher, v. 49, p 171 (2011). http://scitation.aip.org/content/aapt/journal/tpt/49/3/10.1119/1.3555506&lt;br /&gt;
;Glen R., Watsonville, California:http://wildirisdiscovery.blogspot.com&lt;br /&gt;
;Andy Cave, Polytechnic Institute of New York University:http://www.teachengineering.org/view_activity.php?url=collection/nyu_/activities/nyu_train/nyu_train_activity1.xml&lt;br /&gt;
;Jason Harper:http://pobox.com/~JasonHarper/TimeCatcher.html&lt;br /&gt;
;Kyle Forinash and Ray Wisman:Kyle and Ray have developed many activities that use mobile devices and electric circuits to measure physical phenomena. http://mobilescience.wikispaces.com&lt;br /&gt;
&lt;br /&gt;
===More resources===&lt;br /&gt;
EnergyTeachers.org is building a list of where to buy electronics components, tools, and kits: http://energyteachers.org/forum/viewtopic.php?f=26&amp;amp;t=3375&lt;br /&gt;
&lt;br /&gt;
OpenTP is creating lessons for students to study physics in a way to move away from labs merely confirming ancient physics. (in French) https://opentp.fr&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Physics teaching]][[Category:Teaching electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Gender_in_pop_culture&amp;diff=2905</id>
		<title>Gender in pop culture</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Gender_in_pop_culture&amp;diff=2905"/>
		<updated>2024-04-05T01:16:02Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Movies==&lt;br /&gt;
&lt;br /&gt;
===Bechdel test===&lt;br /&gt;
Is there more than one woman in the story, and are they more than foils to the male characters? Pretty rare.&lt;br /&gt;
https://en.wikipedia.org/wiki/Bechdel_test&lt;br /&gt;
&lt;br /&gt;
===Preponderance of Males in non-human movies?===&lt;br /&gt;
;[http://www.imdb.com/title/tt0775552/ Aliens in the Attic, 2009]:4 main aliens male, even though cast is 7 women and 8 men.&lt;br /&gt;
;[http://www.imdb.com/title/tt0126029/ Shrek, 2001]:2 main characters male, all supporting characters besides Fiona male.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Recognizable characters from fiction==&lt;br /&gt;
;Shrek&lt;br /&gt;
:Shrek&lt;br /&gt;
:Donkey&lt;br /&gt;
:Puss in Boots, Shrek III, 2007&lt;br /&gt;
:Fiona&lt;br /&gt;
;Charlie&#039;s Angels&lt;br /&gt;
:Natalie&lt;br /&gt;
:Dylan&lt;br /&gt;
:Alex&lt;br /&gt;
:Bosley&lt;br /&gt;
:Charlie&lt;br /&gt;
;Twilight&lt;br /&gt;
:Bella&lt;br /&gt;
:Jacob&lt;br /&gt;
:Edward&lt;br /&gt;
;Harry Potter&lt;br /&gt;
:Harry&lt;br /&gt;
:Ron&lt;br /&gt;
:Hermione&lt;br /&gt;
:Dumbledore&lt;br /&gt;
:Snape&lt;br /&gt;
;Pulp Fiction&lt;br /&gt;
:Vincent Vega&lt;br /&gt;
:Jules Winnfield&lt;br /&gt;
;Star Wars&lt;br /&gt;
:Obi-Wan&lt;br /&gt;
:Anakin&lt;br /&gt;
:Luke&lt;br /&gt;
:Leia&lt;br /&gt;
:Qui Gon&lt;br /&gt;
:Han Solo&lt;br /&gt;
:Chewbacca&lt;br /&gt;
:R2-D2&lt;br /&gt;
:C-3PO&lt;br /&gt;
:Darth Vader&lt;br /&gt;
:Lando Calrissian&lt;br /&gt;
:Yoda&lt;br /&gt;
:Padmé&lt;br /&gt;
:Count Dooku&lt;br /&gt;
:Palpatine&lt;br /&gt;
;Lord of the Rings&lt;br /&gt;
:Sam&lt;br /&gt;
:Frodo&lt;br /&gt;
:Gandalf&lt;br /&gt;
:Merry&lt;br /&gt;
:Pippin&lt;br /&gt;
:Bilbo&lt;br /&gt;
:Aragorn&lt;br /&gt;
:Arwen&lt;br /&gt;
:Galadriel&lt;br /&gt;
:Elrond&lt;br /&gt;
:Legolas&lt;br /&gt;
:Gimli&lt;br /&gt;
:Boromir&lt;br /&gt;
:Faramir&lt;br /&gt;
:Saruman&lt;br /&gt;
:Sauron&lt;br /&gt;
:Smeagol&lt;br /&gt;
:Theoden&lt;br /&gt;
:Denethor&lt;br /&gt;
:Eomer&lt;br /&gt;
:Eowyn&lt;br /&gt;
:Grima Wormtongue&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2904</id>
		<title>Circuits for teaching physics</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2904"/>
		<updated>2024-04-05T01:12:14Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Example circuits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Rationale===&lt;br /&gt;
I&#039;ve taught my students to build electronic circuits, and, separately, I&#039;ve taught my students to devise their own experimental apparatus. While these two movements in my teaching have been two of the most successful, I&#039;ve yet to successfully combine them, yet to ask them to build their own circuits as lab apparatus for studying something else. It&#039;s so promising that I&#039;ve decided to ask others to join me in the trial.&lt;br /&gt;
&lt;br /&gt;
Having our physics students build their own apparatus might have multiple benefits:&lt;br /&gt;
#Affordability&lt;br /&gt;
##Save schools that would otherwise buy commercial apparatus a large fraction of the cost.&lt;br /&gt;
##Allow schools that would otherwise miss out because they couldn&#039;t afford the commercial apparatus.&lt;br /&gt;
##Allow more students of more schools to borrow lab equipment for homework, or even have more students own their lab equipment outright.&lt;br /&gt;
#Pedagogical benefits&lt;br /&gt;
##We hope to increase student ownership of the process of learning in the laboratory. Students may be more interested in the measurement of a physical variable when they have created the apparatus.&lt;br /&gt;
##Allow students to learn a skill to be used in other environments, including students who would not elect to learn circuits or programming, but would elect physics.&lt;br /&gt;
##Attract students interested in circuits and programming to physics.&lt;br /&gt;
#Curriculum&lt;br /&gt;
##Learning about identifying resistors and what makes appropriate substitutions helps students understand why orders of magnitude are an important way of making comparisons. After they&#039;ve started to learn the resistor color code, I ask my students which color-band is the most important, i.e. getting which one wrong would most likely affect the operation of the circuit.&lt;br /&gt;
##Specifying or substituting components, for example choosing among diodes or transistors, should help a student learn about the physical characteristics of those components.&lt;br /&gt;
##Students should be less iffy about the nature of electrical connections than students who study physics without building circuits.&lt;br /&gt;
&lt;br /&gt;
===Learning physics with circuits===&lt;br /&gt;
What will students learn about physics with circuits they build?&lt;br /&gt;
&lt;br /&gt;
Traditionally, physics students learn about circuits as a topic of physics after learning about electricity and magnetism. Instead, here I am suggesting we teach students about circuits as tools for learning in a wider range of fields of physics, from mechanics to astronomy, with rich opportunities to learn the traditional things about circuits scattered along the way.&lt;br /&gt;
&lt;br /&gt;
So, to start, students could be expected to learn about the traditional topics in circuits, such as resistance, capacitance, induction, EMF, parallel and series combinations, amplification, and various more advanced topics.&lt;br /&gt;
&lt;br /&gt;
But &#039;&#039;using&#039;&#039; circuits they can investigate waves, interference, optics, kinematics, dynamics, electric and magnetic fields, energy transfers, thermodynamics, the spectrum, and more.&lt;br /&gt;
&lt;br /&gt;
In February, 2014, I took a poll of teachers in the Syracuse area, asking which circuits, from a list I thought might be easy yet useful, they&#039;d most like to make in a workshop to take to their schools. The following table of results shows how important photo-gates are to physics teachers. One could argue that volt-meters are so popular that they&#039;re universally already-owned. Or, one could argue that they are not popular because they are used for studying electricity, not as canonical a topic as the kinematics studied with the photo-gates.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! circuit!! votes&lt;br /&gt;
|-&lt;br /&gt;
| photogates-timer || 12&lt;br /&gt;
|-&lt;br /&gt;
| anemometer || 8&lt;br /&gt;
|-&lt;br /&gt;
| wheel-speedometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| magnetometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| ammeter || 4&lt;br /&gt;
|-&lt;br /&gt;
| digital-thermometer || 4&lt;br /&gt;
|-&lt;br /&gt;
| light-meter || 3&lt;br /&gt;
|-&lt;br /&gt;
| data-logger || 3&lt;br /&gt;
|-&lt;br /&gt;
| volt-meter || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some circuits use only discrete components, many use integrated circuits like the 555 timer or the 741 op amp, and some use micro-controllers to gather data or run a complex algorithm or interface.&lt;br /&gt;
&lt;br /&gt;
The micro-controller requires special consideration, because each unit, be it a chip or a board, can cost anywhere between $1 and $40. With the right programming-circuit and software, a $2 chip can be programmed as easily as a $10 chip, and may be versatile enough to do what some are doing with their $30 boards.&lt;br /&gt;
&lt;br /&gt;
===Sensors===&lt;br /&gt;
There is a multitude of sensors that can be connected to processors or directly to outputs. Sensors can be used to study the physical phenomena sensed, but they also can be used to teach the different ways of processing their signals.&lt;br /&gt;
&lt;br /&gt;
====Analog sensors====&lt;br /&gt;
;Humidity sensors:Humidity sensors may output relative or absolute humidity values, and are often packaged with a temperature sensor so we can convert to the other value through software.&lt;br /&gt;
;Light-dependent resistors:LDRs are usually cadmium sulfide, which changes resistance according to how much light is falling on the cell. Cadmium is a toxic metal, so we usually use non-toxic alternatives like photo-transistors or photo-diodes or solar cells, especially for children&#039;s use. They react to changes in light more slowly than diodes and transistors, but they are easy to model as predictable, variable resistors.&lt;br /&gt;
;Potentiometers and rheostats:Variable resistors are usually a knob or a slider that change resistance from zero to some given value. Some, marked α (alpha) or A, are logarithmically tapered so that they can control audio or light over a wide, exponential range of values. Linear variable resistors are marked β (beta) or B.&lt;br /&gt;
;Thermistors:Temperature-dependent resistors may have a negative or positive temperature coefficient, according to whether their resistance goes down or up when their temperature goes up. See wikipedia for more information, including a discussion of how they can increase temperature because the circuit is adding energy via the current used to sense its resistance. http://en.wikipedia.org/wiki/Thermistor&lt;br /&gt;
;Thermopiles:Thermopiles are semiconductor devices that change resistance or voltage in a circuit depending on their temperature, and they are thermally shielded so that they rise and fall in temperature with remote objects they face through a window in their otherwise heavy insulation. The window is usually made of a material that doesn&#039;t allow visible light, so that it is tuned to sensing temperatures corresponding to a peak wavelength in far infrared. These are the sensors used for non-contact thermometers, like those medical personnel use to take a person&#039;s temperature via ear or mouth.&lt;br /&gt;
====On-off sensors====&lt;br /&gt;
;Passive infrared motion detectors:PIR devices often output a voltage between their supply and 1.5V when not detecting changing infrared light, then short their output to ground when they do detect changing infrared light. When using such PIR detectors with a micro-controller or similar logic ICs, pull the output up with a resistor, which may be an internal feature in micro-controllers like the Arduino, so that the output is clearly high or low.&lt;br /&gt;
;Switches:Switches can be purchased or hand-made from all sorts of materials, like chewing-gum wrappers. A multitude of types of switches can be salvaged from old electronic equipment, like remote controls, tape players, and phones. They connect one or more conduits to one or more other conduits, and may make the connection when pushed, or disconnect when pushed, or toggle between connected and disconnected when pushed and released. They may spring back to a default position or they may stay in any state.&lt;br /&gt;
;Tilt switches:These switches consist of a metal ball or mercury that makes contact only when it is tilted a certain amount. This is how mercury thermostats work.&lt;br /&gt;
;Ultrasonic distance sensors:These sensors send a train of ultrasonic pings when their trigger pin is taken high or low, then set an echo pin high or low for the duration of the flight of the pings to a reflecting object and back.&lt;br /&gt;
;Vibration switches:These switches consist of a stiff wire surrounded by a metal coil that only contacts the wire when shaken.&lt;br /&gt;
&lt;br /&gt;
====Digital-value sensors====&lt;br /&gt;
&lt;br /&gt;
====Commercial sensors====&lt;br /&gt;
There are ways to connect sensors from commercial systems, the most well-known companies being Vernier and PASCO, to circuits—Some sensors output analog values on one wire when powered on two others, while some speak a digital code that may be open to the public. For example, Vernier publishes a guide to connecting their sensors to the Arduino. &amp;lt;ref&amp;gt;http://www.vernier.com/engineering/arduino/&amp;lt;/ref&amp;gt; PASCO explains how the wires on various sensors function.&amp;lt;ref&amp;gt;http://www.pasco.com/support/technical-support/technote/techIDlookup.cfm?TechNoteID=436&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Outputs===&lt;br /&gt;
See [[#Display]] for a discussion of displaying characters.&lt;br /&gt;
====Sound transducers====&lt;br /&gt;
;Speakers:Circuits can vibrate a speaker to make sound, and the pitch, timbre, and/or volume can indicate criteria.&lt;br /&gt;
;Piezo buzzers:Piezo buzzers buzz a certain tone with an applied voltage, but can be made to make more interesting sounds.&lt;br /&gt;
;Piezo elements:Piezo elements click when the voltage applied goes over some threshold, and the clicking can be very fast, so one may make square waves of many frequencies with them.&lt;br /&gt;
====Light transducers====&lt;br /&gt;
All the following transducers may be arranged in character or graphical displays, including light bars, bar graphs, multi-dimensional arrays, and two-dimensional screens.&lt;br /&gt;
;Light emitting diodes:LEDs usually convert a specific voltage to a narrow band of light with a frequency correlated to that voltage. i.e., blue LEDs operate at a higher voltage than red LEDs. LEDs can turn on and off extremely quickly, so dimming is usually handled by running them with a square wave of varying duty cycle. When they&#039;re not busy emitting, LEDs can also be used as photodiodes to detect light levels.&lt;br /&gt;
;Incandescent lamps:Incandescent lamps can be had over a wide range of voltages, and their brightness and color depend on the voltage applied.&lt;br /&gt;
;Plasma lamps:Plasma lamps, for instance neon bulbs, require high voltages to light, but can be visible with very little current.&lt;br /&gt;
;Liquid crystal display:LCDs typically use minuscule amounts of power compared to other ways of displaying characters or graphics. At around $10 per display, they are an inexpensive and efficient way to display a short line or two of text. While many displays are proprietary, there are also many with common protocols that allow easy control.&lt;br /&gt;
====Relays====&lt;br /&gt;
Relays are switches controlled by current, for instance allowing a 5-volt DC system to control a 110-volt AC system without any electrical connection between the two systems.&lt;br /&gt;
;Magnetic relay:Magnetic relays are the switches you may hear in the car when you turn on or off a device, for example when a low-current line to a switch on the dashboard switches a high-current line through the headlights.&lt;br /&gt;
;Solid state relay:SSRs rely on semiconductor properties to allow a small current to light an LED which controls a photo-transistor or light-activated silicon-controlled rectifier (LASCR), thus electrically isolating the two systems through light. They can be ten times the cost of magnetic relays, but can last much longer and act much more quickly.&lt;br /&gt;
&lt;br /&gt;
===Example circuits===&lt;br /&gt;
====Photo-gate timer====&lt;br /&gt;
A photo-gate timer uses light emitters and receivers to detect the passage of an object. The simplest timer would be a single light receiver, such as a photodiode or light-dependent resistor, that darkens when the leading edge of an object passes over it and lightens when that object&#039;s trailing edge passes over it. A circuit could be made to count beats of a clock between the two events. Then, for example, the known length of the object could be divided by the time between the two events to determine the average velocity of the object through the gate.&lt;br /&gt;
&lt;br /&gt;
A more commonly used system in the teaching laboratory is a set of two gates, where the source is not the ambient light but a light-emitting diode (LED) paired with a photodiode designed to be sensitive to the color of the LED, that color usually being infrared. Each gate is triggered when the leading edge of the object first blocks the light. By only paying attention to the leading edge, the timing is independent of the geometry of the object and its shadow. By using infrared instead of visible light, spurious signals from visible light and shadow in the lab are removed, and the receiver does not have to be calibrated for laboratories of varying brightness. The disadvantage of infrared is it is harder to tell whether the emitter is operating—Keep an old cell-phone camera handy; because they lack an infrared filter, they can be used to check IR LEDs.&lt;br /&gt;
&lt;br /&gt;
It is possible to time events without micro-controllers or computers—Shading the first detector could lower voltage enough to trip a monostable 555 to reset a bank of counter ICs. The least-significant counter IC could be fed clock signals from an astable 555. The last detector could likewise disable counting.&lt;br /&gt;
&lt;br /&gt;
But, the complexity of watching multiple gates, ignoring spurious signals, counting time, and reporting that time to a display or computer, makes a micro-controller the best tool for the job.&lt;br /&gt;
&lt;br /&gt;
For an example, see [[photo-gate timer]].&lt;br /&gt;
&lt;br /&gt;
====Wheel-speedometer====&lt;br /&gt;
See [[bicycle speedometer]].&lt;br /&gt;
&lt;br /&gt;
Most speedometers are really rotational frequency-meters, with readings calculated according to the circumference of the spinning object. See [[frequency meter]].&lt;br /&gt;
&lt;br /&gt;
====Anemometer====&lt;br /&gt;
Exactly the same circuit as wheel speedometer, or may use a lookup table instead of a calculation if it does not have a linear response to wind speed.&lt;br /&gt;
&lt;br /&gt;
====Magnetometer====&lt;br /&gt;
Read values from a Hall-effect sensor or an integrated-chip, multi-axis magnetometer. See [[magnetometer]] for more discussion.&lt;br /&gt;
&lt;br /&gt;
====Light-to-sound====&lt;br /&gt;
The conductivity of a light-dependent resistor is proportional to the light falling on it. It can be placed in different parts of a 555-timer circuit to play a variable pitch through a speaker. https://energyteachers.org/project_detail.php?project_id=15&lt;br /&gt;
&lt;br /&gt;
====Ammeter====&lt;br /&gt;
The circuit design depends on whether measuring DC or AC current, and whether in contact or not with the measured circuit.&lt;br /&gt;
&lt;br /&gt;
====Thermometer====&lt;br /&gt;
Measure the voltage across a thermocouple, the resistance across a thermistor, or use an integrated-chip that responds with data to serial commands.&lt;br /&gt;
&lt;br /&gt;
====Light-meter====&lt;br /&gt;
Measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Light-polarization meter====&lt;br /&gt;
For each of two sensors behind two crossed polarizers, measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Data-logging====&lt;br /&gt;
Have the micro-controller write data from whatever input to a memory-chip, or internal memory if sufficient, for retrieval later.&lt;br /&gt;
&lt;br /&gt;
====Voltmeter====&lt;br /&gt;
Measure the voltage between a pin and ground, using a divider when appropriate.&lt;br /&gt;
&lt;br /&gt;
===Micro-controllers===&lt;br /&gt;
There are thousands of integrated circuits that serve specific purposes, such as counting voltage drops on one pin and providing the count as binary on a set of other pins. Micro-controllers allow us to program a chip to serve a custom purpose, for comparison to the previous example, say counting voltage drops on one pin, comparing the period between the last two drops to the average of the last ten periods, to determine if something is slowing down or speeding up, then lighting a green or red LED accordingly. Micro-controllers allow us to customize them through programming, and most can be re-programmed many times, making them a versatile investment.&lt;br /&gt;
====Programming micro-controllers====&lt;br /&gt;
To learn your commands, they micro-controller must be told them, and there are very many ways this can happen, depending on the model of micro-controller. Here are some methods I&#039;ve used, with costs for comparison:&lt;br /&gt;
#Use PICAXE computer software (free) to write the commands in BASIC, compile it, and send it via serial cable ($10-20) to a PICAXE chip ($3-$10) in a programming circuit ($5), then put the chip in the working circuit.&lt;br /&gt;
#Use linux program MCU8051 (free) to write and compile a program in 8051 [http://en.wikipedia.org/wiki/Assembly_language assembly language], and send it via serial cable ($10-$20) to a parallel-eeprom programming board ($100) to an Atmel 89C2051 chip ($1).&lt;br /&gt;
#Use Arduino software (free) to write and compile a program in C and send it via serial or USB to an Arduino board ($10-$30) or an AVR micro-controller ($3-$5), on a breadboard ($5) with supporting components ($1), that has been loaded with the Arduino bootloader.&lt;br /&gt;
Many of these scenarios require only very minimal computers by today&#039;s standards. In fact, it&#039;s best to have an older computer (late 1990s, early 200s) that has built-in serial ports and can easily be outfitted with Linux.&lt;br /&gt;
&lt;br /&gt;
Learning to program micro-controllers is not completely unlike learning to program computers, and should be an enriching experience for students.&lt;br /&gt;
===Data-handling===&lt;br /&gt;
There are many ways to read measurements.&lt;br /&gt;
====Storage====&lt;br /&gt;
Some applications require data to be stored and retrieved later, such as in long-term anemometry or thermodynamic studies.&lt;br /&gt;
*A single count, such as in a timing application using pulses from a 555 IC, can be stored in a digital counter IC.&lt;br /&gt;
*Micro-controllers can store data in flash memory to be retrieved via a display or serial communications.&lt;br /&gt;
*Micro-controllers can write to disk drives, flash memory, or removable flash memory.&lt;br /&gt;
*A circuit can communicate with a computer via a serial connection.&lt;br /&gt;
====Display====&lt;br /&gt;
Digital circuits can have a numeric display.&lt;br /&gt;
*1-4 digits are best displayed by seven-segment LED displays, which can be directly driven by micro-controllers with at least 8 output pins, or driven by counter or driver ICs.&lt;br /&gt;
*More digits and/or text can be displayed by LCD displays ($10-$20).&lt;br /&gt;
*Many circuits can communicate with a computer to display and/or store readings, usually through a serial port.&lt;br /&gt;
*A voltmeter across two points of a circuit can be used with a lookup table to determine measurements.&lt;br /&gt;
&lt;br /&gt;
===Supporting apparatus===&lt;br /&gt;
Many laboratories will need equipment such as computers for programming micro-controllers or oscilloscopes for visualizing outputs of sensing circuits.&lt;br /&gt;
&lt;br /&gt;
====Power supplies====&lt;br /&gt;
There are many considerations when choosing power supplies&lt;br /&gt;
;Safety:Batteries are excellent for safety. One thing to watch out for is students putting two 9V batteries together, since their terminals almost beg to be put together. 9V batteries are also dangerous to store, having both terminals so close to each other, leading to inadvertent shorts.&lt;br /&gt;
;Economy:I use rechargeable batteries, which easily last through a school-day or through a unit, then go into a recharger.&lt;br /&gt;
;Voltage:Some components, like the rugged 555 timer IC, can take a wide range of voltages from supplies. Micro-controllers usually have much stricter operating ranges, and some are incompatible with others, two popular ranges being 4.5V-5.5V, and 3.0V-3.5V.&lt;br /&gt;
My students usually use a 2xAA, 3xAA, or 4xAAA battery pack or a 9V battery, all which connect to a breadboard with a standard 9V-style-terminated cable.&lt;br /&gt;
&lt;br /&gt;
====Solderless breadboards====&lt;br /&gt;
My students use and re-use versatile solderless breadboards. It takes a lesson for them to understand how it makes connections in circuits, and I&#039;ve found students of all ages over 9 are capable, after a few times practice, of understanding the difference between an abstract diagram and the actual placement of components on the breadboard.&lt;br /&gt;
====Tools for an electronics lab====&lt;br /&gt;
*Needle-nose pliers.&lt;br /&gt;
*Fine wire cutters.&lt;br /&gt;
*Chip pullers and inserters.&lt;br /&gt;
*Digital multimeters; measuring DCV, ACV, mA, A, Ω, and Hz, preferably.&lt;br /&gt;
*Transistor/diode tester (called &amp;quot;Component Tester&amp;quot; at Radio Shack).&lt;br /&gt;
*Oscilloscope.&lt;br /&gt;
&lt;br /&gt;
===Sample lessons===&lt;br /&gt;
Ask each student per pair to make a circuit that produces a tone that they expect to be harmonious with the other student&#039;s, then examine the two as X and Y components on an oscilloscope, enjoying the lissajous-figures associated with the harmonic pairs.&lt;br /&gt;
&lt;br /&gt;
Build a spectrometer with a solar cell and a stepper motor, then investigate spectra.&lt;br /&gt;
&lt;br /&gt;
Build a circuit to measure an unknown resistance by comparison with known resistances.&lt;br /&gt;
&lt;br /&gt;
===Teachers using circuits===&lt;br /&gt;
These educators have been kind enough to share their experiences using circuits to teach physics:&lt;br /&gt;
;Peter Siegel, California State Polytechnic University, Pomona:http://www.csupomona.edu/~pbsiegel/&lt;br /&gt;
;John Liu, St. Cloud State University, Minnesota:http://liudr.wordpress.com&lt;br /&gt;
;William Baird et al., Armstrong Atlantic State University, Savannah, Georgia:See their article &#039;&#039;The Light-Emitting Diode as a Light Detector&#039;&#039; in The Physics Teacher, v. 49, p 171 (2011). http://scitation.aip.org/content/aapt/journal/tpt/49/3/10.1119/1.3555506&lt;br /&gt;
;Glen R., Watsonville, California:http://wildirisdiscovery.blogspot.com&lt;br /&gt;
;Andy Cave, Polytechnic Institute of New York University:http://www.teachengineering.org/view_activity.php?url=collection/nyu_/activities/nyu_train/nyu_train_activity1.xml&lt;br /&gt;
;Jason Harper:http://pobox.com/~JasonHarper/TimeCatcher.html&lt;br /&gt;
;Kyle Forinash and Ray Wisman:Kyle and Ray have developed many activities that use mobile devices and electric circuits to measure physical phenomena. http://mobilescience.wikispaces.com&lt;br /&gt;
&lt;br /&gt;
===More resources===&lt;br /&gt;
EnergyTeachers.org is building a list of where to buy electronics components, tools, and kits: http://energyteachers.org/forum/viewtopic.php?f=26&amp;amp;t=3375&lt;br /&gt;
&lt;br /&gt;
OpenTP is creating lessons for students to study physics in a way to move away from labs merely confirming ancient physics. (in French) https://opentp.fr&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Physics teaching]][[Category:Teaching electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Bicycle_speedometer&amp;diff=2903</id>
		<title>Bicycle speedometer</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Bicycle_speedometer&amp;diff=2903"/>
		<updated>2023-06-28T19:04:51Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* About making a bicycle speedometer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==About making a bicycle speedometer==&lt;br /&gt;
When a student in my circuits class asked if one could build a speedometer, I began to seek a simple circuit that would include a switch, a frequency meter, some way to convert that to a speed, and a display.&lt;br /&gt;
&lt;br /&gt;
===Specifications===&lt;br /&gt;
*Use a magnetic reed switch attached to the frame/fork of a bicycle, or a Hall sensor switch.&lt;br /&gt;
*Run on a battery.&lt;br /&gt;
*Include at least a two-digit display. An LCD will save power over an LED display.&lt;br /&gt;
*Include a power switch to save the battery.&lt;br /&gt;
*Weigh as little as possible.&lt;br /&gt;
*Use a breadboard so it can be modified.&lt;br /&gt;
*Optionally include a switch to allow changing tire diameter.&lt;br /&gt;
&lt;br /&gt;
==Versions==&lt;br /&gt;
===AVR===&lt;br /&gt;
[[File:Bicycle-speedometer-Arduino-on-a-board-4-bit-LCD.png|256px|thumb|right|Circuit diagram]]&lt;br /&gt;
This version is similar to my [[frequency meter]], but includes a variable wheel-radius, adjustable by button. It is built around an Atmel 328P AVR micro-controller, programmed using the Arduino IDE.&lt;br /&gt;
&lt;br /&gt;
See [[Arduino program for bicycle speedometer]] for a working code.&lt;br /&gt;
&lt;br /&gt;
====Components====&lt;br /&gt;
See [[Media:Bicycle-speedometer-Arduino-on-a-board-4-bit-LCD.pdf]] for a printable diagram.&lt;br /&gt;
;Atmel 328P AVR micro-controller:&lt;br /&gt;
;TT electronics OH090U, Hallogic Hall-effect sensor:This sensor is uni-polar, meaning it turns on only when it senses a south pole facing its symbol-face, with a strength of about 90 Gauss. A hysteresis of about 10 Gauss helps reduce bounce in the switch.&lt;br /&gt;
;Lumex 1601 character LCD:This LCD operates internally as an 8x2 character display, so the program needs to send characters to the second line for them to appear in the rightmost eight spaces. We use 4-bit mode, so data goes over four lines, and  a total of nine separate lines go from the circuit board to the LCD, including a middle-voltage that controls the contrast.&lt;br /&gt;
;10kΩ resistor:This resistor pulls the micro-controller RESET pin high for normal operation.&lt;br /&gt;
;Two momentary-on push-button switches: One pulls reset low, and the other changes the wheel-diameter.&lt;br /&gt;
;16Mhz crystal:For accurate timing, we use an external 16MHz crystal. A lower frequency would save power, something for a future version.&lt;br /&gt;
;Two 20pF, +/-2pF capacitors:These capacitors allow the crystal to oscillate.&lt;br /&gt;
;0.1µF electrolytic or ceramic capacitor:This capacitor helps smooth the voltage on power busses so switches and signals don&#039;t trip each other.&lt;br /&gt;
====Power supply====&lt;br /&gt;
The LCD is intended to operate between 4.7V and 5.3V. A battery case with a switch and three alkaline AAA cells works well. A 9V battery with a 5V regulator would also work, but waste more energy.&lt;br /&gt;
&lt;br /&gt;
We could save energy by putting the micro-controller to sleep if the sensor doesn&#039;t send a signal for more than, say, 30 seconds. See http://playground.arduino.cc/Learning/ArduinoSleepCode .&lt;br /&gt;
&lt;br /&gt;
===2051===&lt;br /&gt;
[[File:Speedometer-Diagram1.png|256px|thumb|right|Circuit diagram for a bicycle speedometer]]&lt;br /&gt;
&lt;br /&gt;
This version is built around an Atmel 89C2051 micro-controller, driving a two-digit LED display.&lt;br /&gt;
&lt;br /&gt;
The circuit uses a common-anode layout since the 2051&#039;s output ports can sink up to 20mA of current.&lt;br /&gt;
&lt;br /&gt;
Since the digits are shown in an alternating fashion, we can use a 10-pin display or tie together parallel pins of an 18-pin display.&lt;br /&gt;
&lt;br /&gt;
We could use PNP transistors instead of MOSFETs but we&#039;d need a resistor between the micro-controller and the base of the transistor.&lt;br /&gt;
&lt;br /&gt;
If the power supply can go above 5.5V, for example if it is four AA or AAA cells, then a voltage regulator or a step-down power diode will be necessary, which will be a waste.&lt;br /&gt;
&lt;br /&gt;
====Components====&lt;br /&gt;
;Atmel 89C2051:This is a very cheap (~$1) micro-controller that can run on 2.7 to 6 volts. To program the C variant requires a flash programmer with a 12V power supply. There is an S variant that can be serially programmed in-circuit.&lt;br /&gt;
;Lumex LDD-M512RI-RA:This is a dual-digit, seven-segment display, where the LED&#039;s cathodes for each digit are tied together to reduce the number of pins to 10. This means that unless both digits are the same, we need to alternate rapidly between showing one and the other by allowing current into one anode or the other. The LEDs are green for excellent visibility in daylight.&lt;br /&gt;
;Fairchild BS270:This is an N-channel MOSFET suited to switching at logic levels (3-5V). The current that goes through depends on the voltage between the gate and source, and the switching happens in nanoseconds. When the voltage at the gate is equal to or lower than the source, no current is allowed from drain to source. Since more current is allowed when the voltage at the gate is much higher than at the source, this N-channel MOSFET is better suited to a common cathode display. I&#039;d like to find a better MOSFET for this common-anode display, and I welcome suggestions on the [[Talk:Bicycle_speedometer|discussion]] page.&lt;br /&gt;
;11MHz crystal:The 2051 can run up to 24MHz. We should use the slowest possible crystal to save energy. The 2051 uses half as much energy running at 8MHz as it does running at 24MHz. At 5V with an 11MHz crystal, the chip will use about 40mW, plus whatever it takes to drive the LEDs, which is about another 40mW with the initial circuit shown.&lt;br /&gt;
;22pF capacitors:These two capacitors keep the crystal ringing, and need to be between 20pF and 40pF.&lt;br /&gt;
;10µF capacitors:One electrolytic capacitor is used to smooth the power supply. This is probably unnecessary if hefty batteries are used and all the connections are short and good, but I&#039;m using a solderless breadboard. The other 10µF capacitor runs the reset circuit which ensures that the program doesn&#039;t try starting until the crystal is ringing properly.&lt;br /&gt;
;33kΩ resistor:This resistor can be anywhere in the tens-of-thousands range, and brings the capacitor attached to the reset pin low a few milliseconds after the circuit is powered.&lt;br /&gt;
;220Ω resistors:This array limits the current passing through each LED, as controlled by the output pins on the 2051. In combination with the BS270, the current through each LED is limited to about 2mA by these resistors. Lower resistors would allow for a brighter display, but use more power.&lt;br /&gt;
;Reed switch:A reed switch needs to be attached to the frame of the bike so that it senses a magnet attached to a spoke of the wheel once per revolution.&lt;br /&gt;
;Power switch:Without a power switch the circuit would consume a battery in a few days or less. It should be attached to one of the wires from the battery.&lt;br /&gt;
&lt;br /&gt;
====Power supply====&lt;br /&gt;
We can use three AAA or AA cells which would provide 3.6V to 5.1V, or one lithium 3.7V cell. Or, we can use a 9V battery with a voltage regulator. A coin battery would not last a day if we left the switch on.&lt;br /&gt;
&lt;br /&gt;
=====Saving battery-life=====&lt;br /&gt;
If we used an LCD display instead, we&#039;d double or triple the life of the battery.&lt;br /&gt;
&lt;br /&gt;
If we programmed the 2051 to go into idle mode when the bike wasn&#039;t moving after a few seconds, we&#039;d double the life of the battery.&lt;br /&gt;
&lt;br /&gt;
If we used a very slow crystal, sub-MHz, we could almost double the life of the battery.&lt;br /&gt;
&lt;br /&gt;
If we used three 1.2V NiMH batteries or some other 3.6V supply, we could double the life of the battery.&lt;br /&gt;
&lt;br /&gt;
Combining all of the above might increase the battery-life more than ten-fold. Note that commercial bike-computers use LCDs, coin-sized batteries, and smart power-down modes.&lt;br /&gt;
&lt;br /&gt;
We could replace the electrolytic capacitors with film capacitors.&lt;br /&gt;
&lt;br /&gt;
To get the micro-controller to enter a power-down mode would save the most energy. It would require a logic circuit that allowed the reed switch to raise the voltage on the reset pin only if the program isn&#039;t running already.&lt;br /&gt;
*Special attention must be paid to ports P1.0 and P1.1, which can sink current, wasting power. From the datasheet: &amp;quot;The P1.0 and P1.1 should be set to &#039;0&#039; if no external pull-ups are used, or set to &#039;1&#039; if external pull-ups are used.&amp;quot;&lt;br /&gt;
*We need to pay attention to what happens to the ports that control the transistors that control the common anodes.&lt;br /&gt;
*The reed-switch should be in it&#039;s own serial circuit with a resistor to V+, so that it creates a signal usable by the logic controlling reset no matter the status of the input pin to which it is normally connected. So, RST = (C-R voltage) OR ( ( REED SWITCH ) NOR ( CONTROL PIN) ). That logic can be achieved with NOR gates only if desired, considering the part before OR as A and the part after OR as B, as ( A NOR B ) NOR ( A NOR B ). Thus, we can use a chip with five NOR gates. I am also investigating using a transistor-based logic, where the software-controlled pin and reed switch NOR through two transistors, then that is OR with the reset capacitor through two more transistors.&lt;br /&gt;
&lt;br /&gt;
If we used an 89S2051 instead of an 89C2051, the micro-controller would use half the power when active, and we could use the reed switch as an interrupt to wake the machine from power down mode. An 89S2051 costs $1.80 and an 89C2051 costs $0.90. If the user is silly enough to use non-rechargeable batteries, they certainly should opt for the more expensive yet more efficient micro-controller. Also, the higher price would pay for itself if it replaced the extra circuitry required to wake the C variant from power-down if that was part of the program.&lt;br /&gt;
&lt;br /&gt;
====Program====&lt;br /&gt;
=====Watching a magnet go around and around=====&lt;br /&gt;
My program running on the 2051 runs a timer that counts up every machine cycle, which is once every 12 oscillations of the crystal. When it senses a grounded voltage on the pin (6) attached to the reed switch, it enters an &amp;quot;interrupt&amp;quot; subroutine that checks to see how much time has passed. If only a few microseconds has passed since the last grounding, it knows the reed switch is just bouncing from the last hit. If a reasonable amount of time has passed, between a few tens of milliseconds and a few seconds, it calculates the speed in miles per hour by dividing the circumference of the wheel by the time elapsed since the magnet last passed. While waiting for the next interrupt, it displays the two digits of the speed. If many seconds pass with no grounding by the reed switch, the program figures the bike is not moving or is being walked, so it shuts off the display.&lt;br /&gt;
&lt;br /&gt;
=====Displaying the digits on a shared-pin LED display=====&lt;br /&gt;
Since the two digits share the same cathode-pins, we can only show one at a time. We flip back and forth so quickly, about five thousand times a second, that it&#039;s imperceivable. The value of each digit is stored in a byte of memory, actually not the value [0-9] but the combination of bits to make the right LEDs on the display light up. For example, &#039;8&#039; requires all seven bits, while &#039;7&#039; requires just the first three.&lt;br /&gt;
&lt;br /&gt;
==Datasheets==&lt;br /&gt;
;Atmel 89C2051:http://www.atmel.com/Images/doc0368.pdf&lt;br /&gt;
;Lumex LDD-M512RI-RA:http://www.lumex.com/specs/LDD-M512RI-RA.pdf&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
See [[PG302]] for discussion on programming the 2051.&lt;br /&gt;
&lt;br /&gt;
See [[frequency meter]] for more discussion on timing.&lt;br /&gt;
&lt;br /&gt;
See &amp;quot;Bicycle Freewheeling with Air Drag as a Physics Experiment&amp;quot; by Paul Janssen and Ewald Janssens in The Physics Teacher, volume 53, number 25 (2015): http://dx.doi.org/10.1119/1.4904237 (subscription or purchase required for full text access). The publisher provides a supplementary document about the circuit in a guest-accessible FTP server: ftp://ftp.aip.org/epaps/phys_teach/E-PHTEAH-53-010501&lt;br /&gt;
&lt;br /&gt;
[[Category:Electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=EDUC_6470_Week_6&amp;diff=2902</id>
		<title>EDUC 6470 Week 6</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=EDUC_6470_Week_6&amp;diff=2902"/>
		<updated>2023-01-04T01:22:27Z</updated>

		<summary type="html">&lt;p&gt;Shawn: /* Readings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Readings for [[EDUC 6470]], Spring 2010.&lt;br /&gt;
&lt;br /&gt;
==Readings==&lt;br /&gt;
;French and Russell, 2002&lt;br /&gt;
The authors write about how their intro biology course for mixed majors is based on scenarios, leading questions, and group work periods. Tools include concept maps and flow charts. The course tightens the circle of training the trainers by having seniors and grads interested in education be the facilitators for the freshman class. Facilitators act as a sort of super note-taker, keeping the thinking of the student body in line with expectations and directions, making explicit the links in the curriculum, for example showing a concept map from the previous lecture to emphasize/reinforce the constructivist nature of the learning. The facilitator allows the instructor not to get distracted by either the A/V equipment, paper handouts, or homework collection.&lt;br /&gt;
&lt;br /&gt;
Are the facilitators getting enough credit for their work? Is the experience worth the same (or more) as the pay they deserve?&lt;br /&gt;
&lt;br /&gt;
;Crawford, Krajcik, and Marx, 1999&lt;br /&gt;
I wonder whether well-contextualized inquiries are often taught at the same conceptual level as a lessened-inquiry science course for the same age? I&#039;m thinking about physics majors, and whether a high energy theorist could spring from a curriculum path that involved much more inquiry. Often physics professors tell me they&#039;re fine with radical reforms only for their non-majors courses.&lt;br /&gt;
&lt;br /&gt;
Does the difficulty of putting some content into an inquiry-based curriculum say something about that content, if such a difficulty exists for reasons intrinsic to the content? Should we alter our content goals just as we alter our pedagogy?&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Category:Physics_teaching&amp;diff=2901</id>
		<title>Category:Physics teaching</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Category:Physics_teaching&amp;diff=2901"/>
		<updated>2023-01-04T01:10:11Z</updated>

		<summary type="html">&lt;p&gt;Shawn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Teaching]]&lt;br /&gt;
[[Category:Physics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
	<entry>
		<id>https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2900</id>
		<title>Circuits for teaching physics</title>
		<link rel="alternate" type="text/html" href="https://shawnreeves.net//wiki/index.php?title=Circuits_for_teaching_physics&amp;diff=2900"/>
		<updated>2023-01-04T01:07:23Z</updated>

		<summary type="html">&lt;p&gt;Shawn: recategorized from teaching physics to physics teaching, joining other pages.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Rationale===&lt;br /&gt;
I&#039;ve taught my students to build electronic circuits, and, separately, I&#039;ve taught my students to devise their own experimental apparatus. While these two movements in my teaching have been two of the most successful, I&#039;ve yet to successfully combine them, yet to ask them to build their own circuits as lab apparatus for studying something else. It&#039;s so promising that I&#039;ve decided to ask others to join me in the trial.&lt;br /&gt;
&lt;br /&gt;
Having our physics students build their own apparatus might have multiple benefits:&lt;br /&gt;
#Affordability&lt;br /&gt;
##Save schools that would otherwise buy commercial apparatus a large fraction of the cost.&lt;br /&gt;
##Allow schools that would otherwise miss out because they couldn&#039;t afford the commercial apparatus.&lt;br /&gt;
##Allow more students of more schools to borrow lab equipment for homework, or even have more students own their lab equipment outright.&lt;br /&gt;
#Pedagogical benefits&lt;br /&gt;
##We hope to increase student ownership of the process of learning in the laboratory. Students may be more interested in the measurement of a physical variable when they have created the apparatus.&lt;br /&gt;
##Allow students to learn a skill to be used in other environments, including students who would not elect to learn circuits or programming, but would elect physics.&lt;br /&gt;
##Attract students interested in circuits and programming to physics.&lt;br /&gt;
#Curriculum&lt;br /&gt;
##Learning about identifying resistors and what makes appropriate substitutions helps students understand why orders of magnitude are an important way of making comparisons. After they&#039;ve started to learn the resistor color code, I ask my students which color-band is the most important, i.e. getting which one wrong would most likely affect the operation of the circuit.&lt;br /&gt;
##Specifying or substituting components, for example choosing among diodes or transistors, should help a student learn about the physical characteristics of those components.&lt;br /&gt;
##Students should be less iffy about the nature of electrical connections than students who study physics without building circuits.&lt;br /&gt;
&lt;br /&gt;
===Learning physics with circuits===&lt;br /&gt;
What will students learn about physics with circuits they build?&lt;br /&gt;
&lt;br /&gt;
Traditionally, physics students learn about circuits as a topic of physics after learning about electricity and magnetism. Instead, here I am suggesting we teach students about circuits as tools for learning in a wider range of fields of physics, from mechanics to astronomy, with rich opportunities to learn the traditional things about circuits scattered along the way.&lt;br /&gt;
&lt;br /&gt;
So, to start, students could be expected to learn about the traditional topics in circuits, such as resistance, capacitance, induction, EMF, parallel and series combinations, amplification, and various more advanced topics.&lt;br /&gt;
&lt;br /&gt;
But &#039;&#039;using&#039;&#039; circuits they can investigate waves, interference, optics, kinematics, dynamics, electric and magnetic fields, energy transfers, thermodynamics, the spectrum, and more.&lt;br /&gt;
&lt;br /&gt;
In February, 2014, I took a poll of teachers in the Syracuse area, asking which circuits, from a list I thought might be easy yet useful, they&#039;d most like to make in a workshop to take to their schools. The following table of results shows how important photo-gates are to physics teachers. One could argue that volt-meters are so popular that they&#039;re universally already-owned. Or, one could argue that they are not popular because they are used for studying electricity, not as canonical a topic as the kinematics studied with the photo-gates.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! circuit!! votes&lt;br /&gt;
|-&lt;br /&gt;
| photogates-timer || 12&lt;br /&gt;
|-&lt;br /&gt;
| anemometer || 8&lt;br /&gt;
|-&lt;br /&gt;
| wheel-speedometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| magnetometer || 7&lt;br /&gt;
|-&lt;br /&gt;
| ammeter || 4&lt;br /&gt;
|-&lt;br /&gt;
| digital-thermometer || 4&lt;br /&gt;
|-&lt;br /&gt;
| light-meter || 3&lt;br /&gt;
|-&lt;br /&gt;
| data-logger || 3&lt;br /&gt;
|-&lt;br /&gt;
| volt-meter || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some circuits use only discrete components, many use integrated circuits like the 555 timer or the 741 op amp, and some use micro-controllers to gather data or run a complex algorithm or interface.&lt;br /&gt;
&lt;br /&gt;
The micro-controller requires special consideration, because each unit, be it a chip or a board, can cost anywhere between $1 and $40. With the right programming-circuit and software, a $2 chip can be programmed as easily as a $10 chip, and may be versatile enough to do what some are doing with their $30 boards.&lt;br /&gt;
&lt;br /&gt;
===Sensors===&lt;br /&gt;
There is a multitude of sensors that can be connected to processors or directly to outputs. Sensors can be used to study the physical phenomena sensed, but they also can be used to teach the different ways of processing their signals.&lt;br /&gt;
&lt;br /&gt;
====Analog sensors====&lt;br /&gt;
;Humidity sensors:Humidity sensors may output relative or absolute humidity values, and are often packaged with a temperature sensor so we can convert to the other value through software.&lt;br /&gt;
;Light-dependent resistors:LDRs are usually cadmium sulfide, which changes resistance according to how much light is falling on the cell. Cadmium is a toxic metal, so we usually use non-toxic alternatives like photo-transistors or photo-diodes or solar cells, especially for children&#039;s use. They react to changes in light more slowly than diodes and transistors, but they are easy to model as predictable, variable resistors.&lt;br /&gt;
;Potentiometers and rheostats:Variable resistors are usually a knob or a slider that change resistance from zero to some given value. Some, marked α (alpha) or A, are logarithmically tapered so that they can control audio or light over a wide, exponential range of values. Linear variable resistors are marked β (beta) or B.&lt;br /&gt;
;Thermistors:Temperature-dependent resistors may have a negative or positive temperature coefficient, according to whether their resistance goes down or up when their temperature goes up. See wikipedia for more information, including a discussion of how they can increase temperature because the circuit is adding energy via the current used to sense its resistance. http://en.wikipedia.org/wiki/Thermistor&lt;br /&gt;
;Thermopiles:Thermopiles are semiconductor devices that change resistance or voltage in a circuit depending on their temperature, and they are thermally shielded so that they rise and fall in temperature with remote objects they face through a window in their otherwise heavy insulation. The window is usually made of a material that doesn&#039;t allow visible light, so that it is tuned to sensing temperatures corresponding to a peak wavelength in far infrared. These are the sensors used for non-contact thermometers, like those medical personnel use to take a person&#039;s temperature via ear or mouth.&lt;br /&gt;
====On-off sensors====&lt;br /&gt;
;Passive infrared motion detectors:PIR devices often output a voltage between their supply and 1.5V when not detecting changing infrared light, then short their output to ground when they do detect changing infrared light. When using such PIR detectors with a micro-controller or similar logic ICs, pull the output up with a resistor, which may be an internal feature in micro-controllers like the Arduino, so that the output is clearly high or low.&lt;br /&gt;
;Switches:Switches can be purchased or hand-made from all sorts of materials, like chewing-gum wrappers. A multitude of types of switches can be salvaged from old electronic equipment, like remote controls, tape players, and phones. They connect one or more conduits to one or more other conduits, and may make the connection when pushed, or disconnect when pushed, or toggle between connected and disconnected when pushed and released. They may spring back to a default position or they may stay in any state.&lt;br /&gt;
;Tilt switches:These switches consist of a metal ball or mercury that makes contact only when it is tilted a certain amount. This is how mercury thermostats work.&lt;br /&gt;
;Ultrasonic distance sensors:These sensors send a train of ultrasonic pings when their trigger pin is taken high or low, then set an echo pin high or low for the duration of the flight of the pings to a reflecting object and back.&lt;br /&gt;
;Vibration switches:These switches consist of a stiff wire surrounded by a metal coil that only contacts the wire when shaken.&lt;br /&gt;
&lt;br /&gt;
====Digital-value sensors====&lt;br /&gt;
&lt;br /&gt;
====Commercial sensors====&lt;br /&gt;
There are ways to connect sensors from commercial systems, the most well-known companies being Vernier and PASCO, to circuits—Some sensors output analog values on one wire when powered on two others, while some speak a digital code that may be open to the public. For example, Vernier publishes a guide to connecting their sensors to the Arduino. &amp;lt;ref&amp;gt;http://www.vernier.com/engineering/arduino/&amp;lt;/ref&amp;gt; PASCO explains how the wires on various sensors function.&amp;lt;ref&amp;gt;http://www.pasco.com/support/technical-support/technote/techIDlookup.cfm?TechNoteID=436&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Outputs===&lt;br /&gt;
See [[#Display]] for a discussion of displaying characters.&lt;br /&gt;
====Sound transducers====&lt;br /&gt;
;Speakers:Circuits can vibrate a speaker to make sound, and the pitch, timbre, and/or volume can indicate criteria.&lt;br /&gt;
;Piezo buzzers:Piezo buzzers buzz a certain tone with an applied voltage, but can be made to make more interesting sounds.&lt;br /&gt;
;Piezo elements:Piezo elements click when the voltage applied goes over some threshold, and the clicking can be very fast, so one may make square waves of many frequencies with them.&lt;br /&gt;
====Light transducers====&lt;br /&gt;
All the following transducers may be arranged in character or graphical displays, including light bars, bar graphs, multi-dimensional arrays, and two-dimensional screens.&lt;br /&gt;
;Light emitting diodes:LEDs usually convert a specific voltage to a narrow band of light with a frequency correlated to that voltage. i.e., blue LEDs operate at a higher voltage than red LEDs. LEDs can turn on and off extremely quickly, so dimming is usually handled by running them with a square wave of varying duty cycle. When they&#039;re not busy emitting, LEDs can also be used as photodiodes to detect light levels.&lt;br /&gt;
;Incandescent lamps:Incandescent lamps can be had over a wide range of voltages, and their brightness and color depend on the voltage applied.&lt;br /&gt;
;Plasma lamps:Plasma lamps, for instance neon bulbs, require high voltages to light, but can be visible with very little current.&lt;br /&gt;
;Liquid crystal display:LCDs typically use minuscule amounts of power compared to other ways of displaying characters or graphics. At around $10 per display, they are an inexpensive and efficient way to display a short line or two of text. While many displays are proprietary, there are also many with common protocols that allow easy control.&lt;br /&gt;
====Relays====&lt;br /&gt;
Relays are switches controlled by current, for instance allowing a 5-volt DC system to control a 110-volt AC system without any electrical connection between the two systems.&lt;br /&gt;
;Magnetic relay:Magnetic relays are the switches you may hear in the car when you turn on or off a device, for example when a low-current line to a switch on the dashboard switches a high-current line through the headlights.&lt;br /&gt;
;Solid state relay:SSRs rely on semiconductor properties to allow a small current to light an LED which controls a photo-transistor or light-activated silicon-controlled rectifier (LASCR), thus electrically isolating the two systems through light. They can be ten times the cost of magnetic relays, but can last much longer and act much more quickly.&lt;br /&gt;
&lt;br /&gt;
===Example circuits===&lt;br /&gt;
====Photo-gate timer====&lt;br /&gt;
A photo-gate timer uses light emitters and receivers to detect the passage of an object. The simplest timer would be a single light receiver, such as a photodiode or light-dependent resistor, that darkens when the leading edge of an object passes over it and lightens when that object&#039;s trailing edge passes over it. A circuit could be made to count beats of a clock between the two events. Then, for example, the known length of the object could be divided by the time between the two events to determine the average velocity of the object through the gate.&lt;br /&gt;
&lt;br /&gt;
A more commonly used system in the teaching laboratory is a set of two gates, where the source is not the ambient light but a light-emitting diode (LED) paired with a photodiode designed to be sensitive to the color of the LED, that color usually being infrared. Each gate is triggered when the leading edge of the object first blocks the light. By only paying attention to the leading edge, the timing is independent of the geometry of the object and its shadow. By using infrared instead of visible light, spurious signals from visible light and shadow in the lab are removed, and the receiver does not have to be calibrated for laboratories of varying brightness. The disadvantage of infrared is it is harder to tell whether the emitter is operating—Keep an old cell-phone camera handy; because they lack an infrared filter, they can be used to check IR LEDs.&lt;br /&gt;
&lt;br /&gt;
It is possible to time events without micro-controllers or computers—Shading the first detector could lower voltage enough to trip a monostable 555 to reset a bank of counter ICs. The least-significant counter IC could be fed clock signals from an astable 555. The last detector could likewise disable counting.&lt;br /&gt;
&lt;br /&gt;
But, the complexity of watching multiple gates, ignoring spurious signals, counting time, and reporting that time to a display or computer, makes a micro-controller the best tool for the job.&lt;br /&gt;
&lt;br /&gt;
For an example, see [[photo-gate timer]].&lt;br /&gt;
&lt;br /&gt;
====Wheel-speedometer====&lt;br /&gt;
See [[bicycle speedometer]].&lt;br /&gt;
&lt;br /&gt;
Most speedometers are really rotational frequency-meters, with readings calculated according to the circumference of the spinning object. See [[frequency meter]].&lt;br /&gt;
&lt;br /&gt;
====Anemometer====&lt;br /&gt;
Exactly the same circuit as wheel speedometer, or may use a lookup table instead of a calculation if it does not have a linear response to wind speed.&lt;br /&gt;
&lt;br /&gt;
====Magnetometer====&lt;br /&gt;
Read values from a Hall-effect sensor or an integrated-chip, multi-axis magnetometer. See [[magnetometer]] for more discussion.&lt;br /&gt;
&lt;br /&gt;
====Ammeter====&lt;br /&gt;
The circuit design depends on whether measuring DC or AC current, and whether in contact or not with the measured circuit.&lt;br /&gt;
&lt;br /&gt;
====Thermometer====&lt;br /&gt;
Measure the voltage across a thermocouple, the resistance across a thermistor, or use an integrated-chip that responds with data to serial commands.&lt;br /&gt;
&lt;br /&gt;
====Light-meter====&lt;br /&gt;
Measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Light-polarization meter====&lt;br /&gt;
For each of two sensors behind two crossed polarizers, measure the resistance of a light-dependent resistor (LDR), the voltage through a photodiode (like a solar cell), the current through a reverse-biased photodiode, or the current through a photodiode.&lt;br /&gt;
&lt;br /&gt;
====Data-logging====&lt;br /&gt;
Have the micro-controller write data from whatever input to a memory-chip, or internal memory if sufficient, for retrieval later.&lt;br /&gt;
&lt;br /&gt;
====Voltmeter====&lt;br /&gt;
Measure the voltage between a pin and ground, using a divider when appropriate.&lt;br /&gt;
&lt;br /&gt;
===Micro-controllers===&lt;br /&gt;
There are thousands of integrated circuits that serve specific purposes, such as counting voltage drops on one pin and providing the count as binary on a set of other pins. Micro-controllers allow us to program a chip to serve a custom purpose, for comparison to the previous example, say counting voltage drops on one pin, comparing the period between the last two drops to the average of the last ten periods, to determine if something is slowing down or speeding up, then lighting a green or red LED accordingly. Micro-controllers allow us to customize them through programming, and most can be re-programmed many times, making them a versatile investment.&lt;br /&gt;
====Programming micro-controllers====&lt;br /&gt;
To learn your commands, they micro-controller must be told them, and there are very many ways this can happen, depending on the model of micro-controller. Here are some methods I&#039;ve used, with costs for comparison:&lt;br /&gt;
#Use PICAXE computer software (free) to write the commands in BASIC, compile it, and send it via serial cable ($10-20) to a PICAXE chip ($3-$10) in a programming circuit ($5), then put the chip in the working circuit.&lt;br /&gt;
#Use linux program MCU8051 (free) to write and compile a program in 8051 [http://en.wikipedia.org/wiki/Assembly_language assembly language], and send it via serial cable ($10-$20) to a parallel-eeprom programming board ($100) to an Atmel 89C2051 chip ($1).&lt;br /&gt;
#Use Arduino software (free) to write and compile a program in C and send it via serial or USB to an Arduino board ($10-$30) or an AVR micro-controller ($3-$5), on a breadboard ($5) with supporting components ($1), that has been loaded with the Arduino bootloader.&lt;br /&gt;
Many of these scenarios require only very minimal computers by today&#039;s standards. In fact, it&#039;s best to have an older computer (late 1990s, early 200s) that has built-in serial ports and can easily be outfitted with Linux.&lt;br /&gt;
&lt;br /&gt;
Learning to program micro-controllers is not completely unlike learning to program computers, and should be an enriching experience for students.&lt;br /&gt;
===Data-handling===&lt;br /&gt;
There are many ways to read measurements.&lt;br /&gt;
====Storage====&lt;br /&gt;
Some applications require data to be stored and retrieved later, such as in long-term anemometry or thermodynamic studies.&lt;br /&gt;
*A single count, such as in a timing application using pulses from a 555 IC, can be stored in a digital counter IC.&lt;br /&gt;
*Micro-controllers can store data in flash memory to be retrieved via a display or serial communications.&lt;br /&gt;
*Micro-controllers can write to disk drives, flash memory, or removable flash memory.&lt;br /&gt;
*A circuit can communicate with a computer via a serial connection.&lt;br /&gt;
====Display====&lt;br /&gt;
Digital circuits can have a numeric display.&lt;br /&gt;
*1-4 digits are best displayed by seven-segment LED displays, which can be directly driven by micro-controllers with at least 8 output pins, or driven by counter or driver ICs.&lt;br /&gt;
*More digits and/or text can be displayed by LCD displays ($10-$20).&lt;br /&gt;
*Many circuits can communicate with a computer to display and/or store readings, usually through a serial port.&lt;br /&gt;
*A voltmeter across two points of a circuit can be used with a lookup table to determine measurements.&lt;br /&gt;
&lt;br /&gt;
===Supporting apparatus===&lt;br /&gt;
Many laboratories will need equipment such as computers for programming micro-controllers or oscilloscopes for visualizing outputs of sensing circuits.&lt;br /&gt;
&lt;br /&gt;
====Power supplies====&lt;br /&gt;
There are many considerations when choosing power supplies&lt;br /&gt;
;Safety:Batteries are excellent for safety. One thing to watch out for is students putting two 9V batteries together, since their terminals almost beg to be put together. 9V batteries are also dangerous to store, having both terminals so close to each other, leading to inadvertent shorts.&lt;br /&gt;
;Economy:I use rechargeable batteries, which easily last through a school-day or through a unit, then go into a recharger.&lt;br /&gt;
;Voltage:Some components, like the rugged 555 timer IC, can take a wide range of voltages from supplies. Micro-controllers usually have much stricter operating ranges, and some are incompatible with others, two popular ranges being 4.5V-5.5V, and 3.0V-3.5V.&lt;br /&gt;
My students usually use a 2xAA, 3xAA, or 4xAAA battery pack or a 9V battery, all which connect to a breadboard with a standard 9V-style-terminated cable.&lt;br /&gt;
&lt;br /&gt;
====Solderless breadboards====&lt;br /&gt;
My students use and re-use versatile solderless breadboards. It takes a lesson for them to understand how it makes connections in circuits, and I&#039;ve found students of all ages over 9 are capable, after a few times practice, of understanding the difference between an abstract diagram and the actual placement of components on the breadboard.&lt;br /&gt;
====Tools for an electronics lab====&lt;br /&gt;
*Needle-nose pliers.&lt;br /&gt;
*Fine wire cutters.&lt;br /&gt;
*Chip pullers and inserters.&lt;br /&gt;
*Digital multimeters; measuring DCV, ACV, mA, A, Ω, and Hz, preferably.&lt;br /&gt;
*Transistor/diode tester (called &amp;quot;Component Tester&amp;quot; at Radio Shack).&lt;br /&gt;
*Oscilloscope.&lt;br /&gt;
&lt;br /&gt;
===Sample lessons===&lt;br /&gt;
Ask each student per pair to make a circuit that produces a tone that they expect to be harmonious with the other student&#039;s, then examine the two as X and Y components on an oscilloscope, enjoying the lissajous-figures associated with the harmonic pairs.&lt;br /&gt;
&lt;br /&gt;
Build a spectrometer with a solar cell and a stepper motor, then investigate spectra.&lt;br /&gt;
&lt;br /&gt;
Build a circuit to measure an unknown resistance by comparison with known resistances.&lt;br /&gt;
&lt;br /&gt;
===Teachers using circuits===&lt;br /&gt;
These educators have been kind enough to share their experiences using circuits to teach physics:&lt;br /&gt;
;Peter Siegel, California State Polytechnic University, Pomona:http://www.csupomona.edu/~pbsiegel/&lt;br /&gt;
;John Liu, St. Cloud State University, Minnesota:http://liudr.wordpress.com&lt;br /&gt;
;William Baird et al., Armstrong Atlantic State University, Savannah, Georgia:See their article &#039;&#039;The Light-Emitting Diode as a Light Detector&#039;&#039; in The Physics Teacher, v. 49, p 171 (2011). http://scitation.aip.org/content/aapt/journal/tpt/49/3/10.1119/1.3555506&lt;br /&gt;
;Glen R., Watsonville, California:http://wildirisdiscovery.blogspot.com&lt;br /&gt;
;Andy Cave, Polytechnic Institute of New York University:http://www.teachengineering.org/view_activity.php?url=collection/nyu_/activities/nyu_train/nyu_train_activity1.xml&lt;br /&gt;
;Jason Harper:http://pobox.com/~JasonHarper/TimeCatcher.html&lt;br /&gt;
;Kyle Forinash and Ray Wisman:Kyle and Ray have developed many activities that use mobile devices and electric circuits to measure physical phenomena. http://mobilescience.wikispaces.com&lt;br /&gt;
&lt;br /&gt;
===More resources===&lt;br /&gt;
EnergyTeachers.org is building a list of where to buy electronics components, tools, and kits: http://energyteachers.org/forum/viewtopic.php?f=26&amp;amp;t=3375&lt;br /&gt;
&lt;br /&gt;
OpenTP is creating lessons for students to study physics in a way to move away from labs merely confirming ancient physics. (in French) https://opentp.fr&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Physics teaching]][[Category:Teaching electronics]]&lt;/div&gt;</summary>
		<author><name>Shawn</name></author>
	</entry>
</feed>