{"build":"2026-10-26.02:49","articles":[{"slug":"dead-zone-rts","title":"Dead Zone RTS","date":"2026-10-19","summary":"Zombie survival meets real-time strategy. Dead Zone is a browser-based game that runs entirely on the front end, rendered with HTML Canvas. To stay alive, you must fortify your defences against hordes of zombies, scavenge supplies, build your camp and keep it lit through the night.","url":"https://niltoid.com/blog/dead-zone-rts/","tags":["JavaScript","Canvas","RTS","browser game"],"skills":["game development","game design","isometric graphics","JavaScript"],"themes":["games","ai-agents"],"dek":"","bodyText":"It was an incredibly fun experience vibe coding this game from scratch using Claude Code and Codex. It only took about four weeks in total. What a time to be a maker.\n\nZombie survival meets real-time strategy. Dead Zone is a browser-based game that runs entirely on the front end, rendered with HTML Canvas. To stay alive, you must fortify your defences against hordes of zombies, scavenge supplies, build your camp and keep it lit through the night.\n\n  Building up the camp while it's still light.\n\nSupplies have to be found and hauled back to camp. Sending people farther out can bring back more, but it also means running into zombies that have been waiting out there. Back at the base, there are walls, guard towers and places to train and heal your survivors.\n\nNight makes things a bit more interesting. Vision shrinks, and defenders can only shoot zombies they can see in the light. Light towers and flares help keep the perimeter visible, so lighting the camp becomes part of building its defenses.\n\n  Night time, with another wave on the way.\n\nSprite animation\n\nWith no tooling other than those models, the graphics took several tries to get right. I went through some pains teaching Codex a strategy to create high-quality sprite animations of rigged 3D figures. It paid off in the end, and it's now encoded into a skill you can find here.\n\nThe game uses directional walking and running animations for its survivors and zombies.\n\n  Soldier walkingBuilder walkingHeavy walking\n\n  WalkerRunning exploderBrute walking\n\nThere's also an eight-direction turnaround for the armored truck:\n\nSurvival is endless: the waves keep coming until the headquarters falls.\n\nPlay the game","projects":[{"name":"Dead Zone RTS","repo":"https://github.com/asaeed/zombie","live":"https://asaeed.github.io/zombie/"}],"links":{"body":["https://github.com/asaeed/sprite-animation-skill","https://asaeed.github.io/zombie/"]},"media":[{"url":"https://niltoid.com/blog/dead-zone-rts/daytime.jpg","alt":"Dead Zone RTS in daylight, with an isometric camp, guard towers and survivors"},{"url":"https://niltoid.com/blog/dead-zone-rts/nighttime.jpg","alt":"The camp at night, with pools of light, a wave warning and building controls"},{"url":"https://niltoid.com/blog/dead-zone-rts/soldier-walk.gif","alt":"Soldier's sixteen-frame southeast walking cycle"},{"url":"https://niltoid.com/blog/dead-zone-rts/builder-walk.gif","alt":"Builder's sixteen-frame southeast walking cycle"},{"url":"https://niltoid.com/blog/dead-zone-rts/walker-walk.gif","alt":"Grey zombie's sixteen-frame southeast walking cycle"},{"url":"https://niltoid.com/blog/dead-zone-rts/exploder-run.gif","alt":"Exploder's sixteen-frame running cycle with orange markers"},{"url":"https://niltoid.com/blog/dead-zone-rts/suv-turnaround.gif","alt":"White armored truck stepping through eight directional poses"},{"url":"https://niltoid.com/blog/dead-zone-rts/heavy-walk.gif","alt":"Heavy survivor's sixteen-frame southeast walking cycle"},{"url":"https://niltoid.com/blog/dead-zone-rts/brute-walk.gif","alt":"Brute zombie's sixteen-frame southeast walking cycle"}]},{"slug":"video-sync","title":"Video Sync","date":"2026-09-16","summary":"An experimental system for cutting and mixing film visuals with Rekordbox, using two-deck playback, MIDI controls and reusable scenes in a browser.","url":"https://niltoid.com/blog/video-sync/","tags":["tutorial","React","Rekordbox","MIDI","Ableton Link","VJ"],"skills":["Web MIDI","real-time graphics","JavaScript","C++"],"themes":["sound-visuals","ai-agents"],"dek":"","bodyText":"I've been working on a way to put film visuals behind a DJ set. Video Sync takes information from Rekordbox and a MIDI controller, then uses it to cut and mix video in time with the music.\n\n  The Live Console, with the scene queue and two-deck controls beside the video.\n\nEach deck has its own video playback. Channel levels and the crossfader control the visual mix, while Hot Cues and Beat FX can change the loops and effects. A queue of scenes keeps the visuals moving as tracks change.\n\nThe graphics run in a browser, with a separate window for the projector. A small native bridge handles MIDI and Ableton Link, while a local relay carries the performance data. Scenes are reusable arrangements of clips, so they don't have to be built again for every song.\n\nIt's still an experimental proof of concept. The current hardware-tested setup is on macOS with Rekordbox and a DDJ-GRV6. Other controllers need their own mappings, and Windows deck-state integration is still to do.\n\n  The DDJ-GRV6 is the controller I use for testing. Photo: AlphaTheta.\n\nFrom footage to a set\n\n1. Sources & Clips\n\nI start in Scene Studio by opening a scene or importing a local video. In the Sources & Clips tab, I find the bits I want, mark their in and out points, then name and color the clips. These are reusable ranges in the source footage, rather than separate copies of the film.\n\n  Sources & Clips: finding and trimming the footage.\n\n2. Loop Builder\n\nNext I drag those clips onto a timeline measured in bars and beats. I can arrange cuts, layer clips and adjust their speed, framing and opacity, then play the loop at a chosen BPM. The first eight loops map to Hot Cues A–H in list order; the star picks the scene's default loop.\n\n  Loop Builder: arranging the clips into musical loops.\n\n3. Try it in the simulator\n\nSave keeps the editable project; Publish makes it available to the Live Console. After publishing, refresh the console, load a deck, then choose the scene from its Visual scene menu. Without any DJ hardware attached, the on-screen controls act as a simulator: set the BPM, press Play, try the Hot Cues and move the channel levels and crossfader to check the mix.\n\n4. Put it on the projector\n\nConnect the projector as an extended display. In the Live Console, click Open projector output, move the new window onto the projector and click Full screen. The controls stay on the laptop while the projector shows the visuals. Refresh an already-open output window after publishing a revised scene.\n\nFor a live set, connect the DDJ-GRV6, open Rekordbox and run the native bridge alongside the local server. On macOS, the Node process also needs Accessibility permission to read the visible decks. The Bridge drawer in the console shows whether live input and the local media are ready before playing.","projects":[{"name":"video-sync","repo":"https://github.com/asaeed/video-sync"}],"links":{"body":["https://alphatheta.com/en/product/dj-controller/ddj-grv6/black/"]},"media":[{"url":"https://niltoid.com/blog/video-sync/video-sync.jpg","alt":"Video Sync's Live Console showing a film scene, scene queue and two-deck mixing controls"},{"url":"https://niltoid.com/blog/video-sync/ddj-grv6.jpg","alt":"AlphaTheta's close-up photograph of the DDJ-GRV6 DJ controller"},{"url":"https://niltoid.com/blog/video-sync/sources-and-clips.jpg","alt":"Scene Studio's Sources and Clips tab with footage, trim timelines and clip settings"},{"url":"https://niltoid.com/blog/video-sync/loop-builder.jpg","alt":"Scene Studio's Loop Builder tab with a film preview, beat timeline and clip inspector"}]},{"slug":"concert-radar","title":"Concert Radar","date":"2026-04-21","summary":"A daily concert roundup and local dashboard that match upcoming shows with my top Spotify artists (or a manually curated artist list). I find it useful.","url":"https://niltoid.com/blog/concert-radar/","tags":["Spotify","Node","Python","CLI"],"skills":["web scraping","data pipelines","CLI design"],"themes":["ai-agents","sound-visuals"],"dek":"","bodyText":"I wanted a way to find upcoming shows by the artists I actually listen to, without checking a pile of different sites. Concert Radar matches concert listings with my Spotify artists and the ones I add manually.\n\n  The dashboard, shown here for Los Angeles, with upcoming shows and my Spotify rotation side by side.\n\nUnderneath are two small command-line tools. spotify-cli reads my listening data, and concerts-cli gathers listings from Songkick, Bandsintown, Ticketmaster and local venue pages. The results are combined so I can look through them in one place.\n\nThere is a daily roundup and a local dashboard for browsing the shows. I can filter by artist, venue or date, and mark shows I'm interested in.\n\nThe tools return JSON, so they can also be used directly from the terminal or by an AI coding assistant. The Spotify CLI is linked above; the concert dashboard runs locally.","projects":[{"name":"Concert Radar"},{"name":"spotify-cli","repo":"https://github.com/asaeed/spotify-cli"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/concert-radar/concert-radar.jpg","alt":"Concert Radar's full dashboard with its header, Los Angeles listings and Spotify rotation sidebar"}]},{"slug":"90s-party-mix","title":"90s Party Mix","date":"2025-04-08","summary":"A 44-minute house set I played at a 90s party. Lots of throwbacks and fuzzy memories.","url":"https://niltoid.com/blog/90s-party-mix/","tags":["DJ mix","SoundCloud","house music","90s"],"skills":["DJing","mixing"],"themes":["sound-visuals"],"dek":"","bodyText":"A house set I played at a 90s party. Lots of throwbacks and fuzzy memories.\n\nThe full mix is about 44 minutes. Hit play below.","projects":[],"links":{"soundcloud":"https://soundcloud.com/ahmad-saeed-377628647/90s-party-mix","body":[]},"media":[{"url":"https://niltoid.com/blog/90s-party-mix/cover.jpg","alt":"Illustrated 90s street party with a boombox, yellow car and city skyline at sunset"}]},{"slug":"ind-serv","title":"Indentured Servitude","date":"2023-04-10","summary":"A browser game about making bricks to repay a debt that keeps growing. Built with JavaScript, Canvas and Konva, with no win state.","url":"https://niltoid.com/blog/ind-serv/","tags":["browser game","JavaScript","Canvas","Konva"],"skills":["game development","game design","JavaScript"],"themes":["games"],"dek":"","bodyText":"This game was one of the last things I coded by hand, in the before times. I established the game and graphics engine and got it about 70% of the way there the old-fashioned way. Eventually I recruited Claude to help me finish the job.\n\nIt's a small browser game about being trapped in debt slavery at a Pakistani brick kiln—a hopeless situation. You and your family work endlessly to pay off a debt that you will never overcome.\n\n  Making bricks, with the debt always in view.\n\nYou shovel mud, mold bricks, bake them and load them onto a truck. Each brick earns a little money towards what you owe. Your wife and son join you, but so do the bills. Lodging, fuel and other charges keep adding to the debt. There is no win state. Getting better at making bricks doesn't fix the arrangement.\n\nIt's built with JavaScript, Canvas and Konva. The story events and dialogue live in data files and are triggered by progress through the game. The little sound effects are synthesized in the browser.\n\nThe game ends with some background on debt bondage and links to learn more. You can play it in a desktop or mobile browser.\n\n  The end screen after clicking Accept your fate, shown here using the game's development preview.","projects":[{"name":"ind-serv","repo":"https://github.com/asaeed/ind-serv","live":"https://indenturedgame.com/"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/ind-serv/indentured-servitude.jpg","alt":"A worker shoveling mud at a pixel-art brick kiln, with the debt counter visible"},{"url":"https://niltoid.com/blog/ind-serv/ending.jpg","alt":"The end screen after accepting your fate, revealing that the debt passes to your children"}]},{"slug":"page-divider-studies","title":"Page Divider Studies","date":"2022-04-18","summary":"Four studies in animated page dividers, ranging from SVG scroll cues and line animation to triangular and wavy transitions.","url":"https://niltoid.com/blog/page-divider-studies/","tags":["SVG","JavaScript","CSS","animation"],"skills":["SVG animation","CSS animation","web animation"],"themes":["graphics-3d"],"dek":"","bodyText":"Four page-divider studies exploring different ways to mark a transition between sections.\n\nThe sketches range from an SVG scroll cue and an animated line to triangular and wavy dividers.","projects":[],"links":{"codepen":["https://codepen.io/asaeed/pen/yLpGEwZ","https://codepen.io/asaeed/pen/mdpaEKG","https://codepen.io/asaeed/pen/RwxERJB","https://codepen.io/asaeed/pen/bGowoOZ"],"body":[]},"media":[{"url":"https://niltoid.com/blog/page-divider-studies/codepen-poster.jpg","alt":"Rows of pink and blue triangles from the animated divider study"}]},{"slug":"sparks-and-honey","title":"sparks & honey","date":"2022-02-01","summary":"A freelance marketing-site build for sparks & honey, implemented with a custom Squarespace template.","url":"https://niltoid.com/blog/sparks-and-honey/","tags":["Squarespace","web development","marketing site"],"skills":["template development","UI development"],"themes":[],"dek":"","bodyText":"I built a marketing site for sparks & honey as a freelance project, using a custom Squarespace template.\n\n  The homepage from the earlier site.\n\n  The reports page from the earlier site.\n\nThe reports section collects their intelligence reports in a grid of covers and titles, with links through to the individual reports.\n\n  The introduction to the Intelligence Reports section.\n\nThe site has since rebranded. These screenshots show the earlier version I worked on.","projects":[{"name":"sparks & honey"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/sparks-and-honey/reports.png","alt":"The earlier sparks & honey reports page with its pink navigation bar and a grid of report covers"},{"url":"https://niltoid.com/blog/sparks-and-honey/homepage.png","alt":"The earlier sparks &amp; honey homepage with pink navigation, a white hexagonal background and the heading We Quantify Culture"},{"url":"https://niltoid.com/blog/sparks-and-honey/reports-intro.jpg","alt":"The Intelligence Reports introduction over a darkened collage of report covers"}]},{"slug":"vr-homeroom","title":"VR Homeroom","date":"2020-10-17","summary":"A VR arcade overlay for choosing games, extending sessions, ordering drinks and asking for help, connected to a venue-management server.","url":"https://niltoid.com/blog/vr-homeroom/","tags":["VR","Unity","OpenVR","WebSockets"],"skills":["C#","real-time sync","product design"],"themes":["graphics-3d","games"],"dek":"","bodyText":"I worked on Homeroom with a couple of friends to make running a VR arcade a little easier. One of them ran VR Bar in Dumbo, Brooklyn, so we had somewhere to try it with actual customers.\n\n  Homeroom's coming-soon page from 2018, recovered from the original site.\n\nMy part was the Unity and OpenVR overlay inside the headset. A customer could pick another game, check and extend their session, order a drink or ask for help, without taking the headset off.\n\nEach station stayed in sync with a venue server over WebSockets. The staff side handled station reservations, signing people in, waivers and a wait list. A bit like managing tables in a restaurant, except the tables have people waving controllers around.\n\nOur team included a 3D animator working in Maya and another developer working on the WebSocket server, with me on the overlay. We had a working prototype and two beta customers when the pandemic closed VR Bar and most of the venues we were hoping to work with.","projects":[{"name":"Homeroom"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/vr-homeroom/homeroom.jpg","alt":"Homeroom's 2018 coming-soon landing page with its geometric logo"}]},{"slug":"quick-comic","title":"Quick Comic","date":"2020-02-25","summary":"A political comic-strip maker originally built in Flash, revisited as an early Vue.js editor with draggable characters and a four-panel strip.","url":"https://niltoid.com/blog/quick-comic/","tags":["Vue.js","Vuex","interact.js","Flash"],"skills":["JavaScript","drag and drop","UI development"],"themes":["graphics-3d"],"dek":"","bodyText":"Quick Comic was a little site for making political comic strips. I built the original with Eric Socolofsky, with illustrations by Alex Eben Meyer.\n\n  The original Flash editor.\n\nYou picked a character, dragged it into a panel and gave it something to say. The original ran on Flash with an ASP.NET API.\n\n  A panel from the original site.\n\nIn 2020 I started rebuilding it in Vue.js. So far the rewrite has a four-panel strip, drag-and-drop characters with interact.js, and an editable title held in Vuex. A small start at bringing the old editor back to the browser.","projects":[{"name":"Quick Comic"}],"links":{"body":["https://eben.com/"]},"media":[{"url":"https://niltoid.com/blog/quick-comic/editing.jpg","alt":"The original Quick Comic editor with a three-panel comic and a tray of illustrated characters"},{"url":"https://niltoid.com/blog/quick-comic/cheney.jpg","alt":"A Quick Comic panel with a robot saying Ironic beside an illustrated Dick Cheney"}]},{"slug":"food-photo","title":"Food Photo","date":"2018-11-30","summary":"A phone-friendly React app for an intermittent fasting study, with meal photos, text reminders and a researcher report page.","url":"https://niltoid.com/blog/food-photo/","tags":["React","AWS Lambda","S3","Serverless"],"skills":["JavaScript","camera capture","serverless development"],"themes":[],"dek":"","bodyText":"I built Food Photo pro bono for an intermittent fasting study. The idea was simple: let participants take photos of their meals on their phones, and give the researchers a way to review them.\n\n  A test photo in the preview screen.\n\nIt's a small React app. Take a photo, add an optional caption, mark it as before or after a meal, and submit. The images go to S3. A scheduled job sends text reminders, and a separate report page lets researchers browse the photos.\n\n  The start screen, under the study's 2-A-Day name.\n\nThe backend uses AWS Lambda and the Serverless Framework. I also tried serving the report page directly from a Lambda function. It worked, though I wouldn't make it my first choice for serving a website.","projects":[{"name":"Food Photo"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/food-photo/photo-screen.png","alt":"Food Photo's phone preview showing a cup of coffee, an optional caption and before or after meal controls"},{"url":"https://niltoid.com/blog/food-photo/home-screen.png","alt":"The Food Photo start screen with the 2-A-Day logo and a Begin button"}]},{"slug":"alliance-for-positive-change","title":"Alliance for Positive Change","date":"2017-07-01","summary":"A custom Squarespace template implementation for a small New York City nonprofit, worked on while at frog.","url":"https://niltoid.com/blog/alliance-for-positive-change/","tags":["Squarespace","nonprofit","web development"],"skills":["template development","UI development"],"themes":[],"dek":"","bodyText":"I worked on a custom Squarespace template for Alliance for Positive Change while I was at frog. It's a small nonprofit based in New York City.\n\n  The homepage from the original Squarespace implementation.\n\nThe site brings together the organization's services, ways to get involved, and news and events. My part was the template implementation, bringing the design into Squarespace.\n\nThe Squarespace site linked above is a copy of the version we launched.\n\n  The Get Care overview page in the same template.","projects":[{"name":"Alliance for Positive Change","live":"https://allianceforpositivechange.squarespace.com/"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/alliance-for-positive-change/homepage.jpg","alt":"The original Alliance for Positive Change Squarespace homepage with a purple photo banner and the site's main navigation"},{"url":"https://niltoid.com/blog/alliance-for-positive-change/get-care.jpg","alt":"The Alliance's Get Care page with a blue photo banner, service introduction and a poem beside the text"}]},{"slug":"dots","title":"Dots","date":"2016-07-19","summary":"Experiments with thousands of particles in a browser, using three.js point clouds, custom shaders and interchangeable animators.","url":"https://niltoid.com/blog/dots/","tags":["three.js","particles","point clouds","WebSockets"],"skills":["WebGL","real-time graphics","JavaScript"],"themes":["graphics-3d"],"dek":"","bodyText":"Some more experiments with three.js. Dots is a way to draw thousands of particles in the browser and move them around without making a separate object for every dot.\n\n  Another view of the particle experiments.\n\n  One of the particle experiments running in the browser.\n\nIt uses a point cloud, BufferGeometry and custom shaders to control the positions, sizes and colors. Separate animators work on the same particles, with experiments for waves, spheres, physics and points arranged around a 3D model. The camera moves between views too.\n\nThere is also an input path for camera tracking data over WebSockets. It's a collection of visual experiments rather than a finished app. Click the demo to switch between them.\n\n  The particles arranged into a sphere.","projects":[{"name":"Dots","repo":"https://github.com/asaeed/Dots","live":"https://asaeed.github.io/Dots/"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/dots/dots-waves.png","alt":"Waves of white particles at different depths on a blue background in Dots"},{"url":"https://niltoid.com/blog/dots/dots.jpg","alt":"White particles at different sizes and depths in the Dots browser experiment"},{"url":"https://niltoid.com/blog/dots/dots-sphere.png","alt":"Thousands of white particles forming a sphere in Dots"}]},{"slug":"cubegrid","title":"CubeGrid","date":"2016-04-21","summary":"A grid of cubes that flips in response to an Intel RealSense depth camera, with browser, Electron and openFrameworks versions.","url":"https://niltoid.com/blog/cubegrid/","tags":["three.js","RealSense","openFrameworks","Electron","WebSockets"],"skills":["WebGL","depth cameras","C++","C#","real-time graphics"],"themes":["graphics-3d"],"dek":"","bodyText":"Another experiment with three.js, this time using a grid of cubes and an Intel RealSense depth camera. Movement in front of the camera flips the cubes on screen.\n\n  The browser version, before any camera input.\n\nThe camera talks to a small C# server, which sends tracking data to the browser over WebSockets. The browser handles the drawing and animation. This was also a workaround for the JavaScript support in the RealSense SDK at the time.\n\nI also packaged it as an Electron app and made an openFrameworks version with support for multiple RealSense sensors. Same idea, a few different ways of connecting the camera to the graphics.","projects":[{"name":"CubeGrid","repo":"https://github.com/asaeed/CubeGrid"},{"name":"CubeGridElectron","repo":"https://github.com/asaeed/CubeGridElectron"},{"name":"ofCubeGrid","repo":"https://github.com/asaeed/ofCubeGrid"},{"name":"RealSenseWebsocketServer","repo":"https://github.com/asaeed/RealSenseWebsocketServer"},{"name":"ofRealSenseServer","repo":"https://github.com/asaeed/ofRealSenseServer"}],"links":{"body":["https://github.com/mrdoob/three.js/"]},"media":[{"url":"https://niltoid.com/blog/cubegrid/cubegrid.jpg","alt":"CubeGrid's browser renderer showing blue, green and yellow cube faces"}]},{"slug":"simple-telepresence-robo","title":"Raspberry Pi Telepresence Robot","date":"2016-03-03","summary":"A simplified telepresence robot with live video, pan-and-tilt controls and a display of motion-sensor data.","url":"https://niltoid.com/blog/simple-telepresence-robo/","tags":["Raspberry Pi","Arduino","Node","robotics","video"],"skills":["video streaming","motor control","sensor integration"],"themes":["robots-hardware"],"dek":"","bodyText":"A telepresence robot allows users to interact with remote environments. You see what the robot see’s, hear what it hears, and you’re able to command it to move around and pick up objects. This project is a very simplified version of a telepresence robot. It includes the following features:\n\n– live video streaming\n\n– pan and tilt control\n\n– motion sensor data display","projects":[{"name":"RemoteInteractiveDevice","repo":"https://github.com/asaeed/RemoteInteractiveDevice"}],"links":{"body":[]},"media":[{"url":"https://niltoid.com/blog/simple-telepresence-robo/tele-robot.jpg","alt":"Telepresence robot prototype with a red electronics enclosure and pan-and-tilt mount"}]},{"slug":"unityrts","title":"Unity RTS","date":"2016-01-20","summary":"A small Unity strategy prototype with survivor controls, zombie behaviours, NavMesh movement and pooled bullets.","url":"https://niltoid.com/blog/unityrts/","tags":["Unity","C#","RTS"],"skills":["game development","C#","prototyping"],"themes":["games"],"dek":"","bodyText":"I started playing with a small real-time strategy game in Unity. You select a survivor, send them around the map, and try to deal with the zombies wandering in. Very much a prototype.\n\nThe unit logic is written in C#, with Unity's NavMesh agents handling movement. There are separate behaviours for survivors and zombies, and mouse and touch input for selecting things on the map.\n\nSurvivors can shoot at targets, while zombies lurk, wander and chase survivors. The bullets use an object pool so they can be reused instead of constantly creating new objects.\n\nThis is mostly an experiment in unit controls and enemy behaviour. There are notes in the code about gathering resources and building defenses, but those are ideas rather than a finished game.","projects":[{"name":"UnityRTS","repo":"https://github.com/asaeed/UnityRTS"}],"links":{"body":[]},"media":[]},{"slug":"isometric-cubes","title":"Isometric Cubes","date":"2015-09-03","summary":"A Canvas experiment in drawing isometric cubes with IsomerJS, with a runnable demo on CodePen.","url":"https://niltoid.com/blog/isometric-cubes/","tags":["JavaScript","Canvas","IsomerJS"],"skills":["isometric graphics"],"themes":["graphics-3d"],"dek":"","bodyText":"An HTML canvas experiment using IsomerJS","projects":[{"name":"IsoCubes","repo":"https://github.com/asaeed/IsoCubes"}],"links":{"codepen":"https://codepen.io/asaeed/pen/myREZa","body":["https://github.com/jdan/isomer"]},"media":[{"url":"https://niltoid.com/blog/isometric-cubes/codepen-poster.jpg","alt":"Colorful isometric cubes scattered across a dark background"}]},{"slug":"space-shooter","title":"Space Shooter","date":"2014-05-13","summary":"Two JavaScript and Canvas space-shooter sketches exploring ship movement, scrolling stars, shooting and enemies.","url":"https://niltoid.com/blog/space-shooter/","tags":["JavaScript","Canvas","CodePen","game prototype"],"skills":["game development","animation","JavaScript"],"themes":["games"],"dek":"","bodyText":"A couple of small space-shooter sketches I made on CodePen, using JavaScript and Canvas.\n\nThe first version is just a ship, a scrolling starfield and shooting. The second adds enemies that move towards the ship, with some basic collision detection for the bullets.\n\nBoth versions are embedded below, without enemies first. Click inside the first demo, then use the arrow keys to move and Space to shoot.\n\nThe enemy version currently needs a compatibility fix before it will run again.","projects":[],"links":{"codepen":["https://codepen.io/asaeed/pen/AxbEGa","https://codepen.io/asaeed/pen/NWbORx"],"body":[]},"media":[{"url":"https://niltoid.com/blog/space-shooter/codepen-poster.jpg","alt":"A small spaceship against a black scrolling starfield from the no-enemies CodePen sketch"}]},{"slug":"vine-explorer","title":"Vine Explorer","date":"2013-11-15","summary":"An experimental interface for searching and browsing six-second Vine videos, combining a Python API, HTML5 video, three.js and Box2D.","url":"https://niltoid.com/blog/vine-explorer/","tags":["JavaScript","Python","HTML5 video","three.js","Box2D"],"skills":["video interfaces","physics simulation"],"themes":["sound-visuals"],"dek":"","bodyText":"Vine Explorer allows you to search and browse these 6-second videos in unusual ways. The Vine data is supplied using this Python API. The site is an exploration of HTML5 video elements, three.js, box2djs, and torture by being subjected to endless human absurdity.","projects":[],"links":{"body":["https://github.com/starlock/vino","https://github.com/mrdoob/three.js/","http://box2d-js.sourceforge.net/"]},"media":[{"url":"https://niltoid.com/blog/vine-explorer/vinesphere.png","alt":"Vine Explorer arranging six-second videos on a three-dimensional sphere"},{"url":"https://niltoid.com/blog/vine-explorer/rainingvines.png","alt":"Vine Explorer displaying falling video tiles in its raining vines view"}]},{"slug":"portable-power","title":"Portable Power","date":"2013-07-27","summary":"Trying a portable 2600 mAh power supply with an idle Raspberry Pi.","url":"https://niltoid.com/blog/portable-power/","tags":["Raspberry Pi","batteries"],"skills":["hardware integration"],"themes":["robots-hardware"],"dek":"","bodyText":"My friend Jamie told me about this power supply available for $12 on one of those group deal sites. It’s 2600mAh which seems to power an idle Raspberry Pi for about 5 hours!","projects":[],"links":{"body":["http://www.jamiegilmartin.com/blog/"]},"media":[{"url":"https://niltoid.com/blog/portable-power/img_20130727_115329.jpg","alt":""}]},{"slug":"html5-canvas-animation","title":"HTML5 Canvas Animation","date":"2013-04-15","summary":"Four small Canvas experiments exploring oscillating particles and simple particle animation, with runnable CodePen demos.","url":"https://niltoid.com/blog/html5-canvas-animation/","tags":["JavaScript","Canvas","particles"],"skills":["animation","real-time graphics"],"themes":["graphics-3d"],"dek":"","bodyText":"A few simple experiments with HTML5 Canvas Animation","projects":[],"links":{"codepen":["https://codepen.io/asaeed/pen/kegsx","https://codepen.io/asaeed/pen/CsAdv","https://codepen.io/asaeed/pen/iFtAq","https://codepen.io/asaeed/pen/FvbBh"],"body":[]},"media":[{"url":"https://niltoid.com/blog/html5-canvas-animation/codepen-poster.jpg","alt":"Rainbow-colored particles forming a wave on a dark background"}]},{"slug":"raspberry-pi-arduino-tornado","title":"Raspberry Pi + Arduino + Tornado","date":"2013-03-02","summary":"Using Tornado and Python multiprocessing to handle browser WebSocket requests and Arduino serial communication at the same time.","url":"https://niltoid.com/blog/raspberry-pi-arduino-tornado/","tags":["tutorial","Raspberry Pi","Arduino","Python","Tornado","WebSockets"],"skills":["multiprocessing","serial communication","real-time sync"],"themes":["robots-hardware"],"dek":"","bodyText":"Tornado is a great open source, Python based web framework.  It is designed to be light-weight, easily scalable, non-blocking and it supports websockets and some other nice features.  What’s more, it runs smooth and quick on the Raspberry Pi.\n\nThus far, my experiments with the Raspberry Pi have involved running Node.js on it to serve web pages and to interact over serial with an Arduino.  Here are some posts on how to do that:\n\n1.  Raspberry Pi Setup\n2.  Raspberry Pi + Arduino: Getting Started\n3.  Raspberry Pi + Arduino + Node = Home Automation\n\nI wanted to try accomplishing something similar using Python.  Specifically, a Python program which can simultaneously handle web requests and communicate with an Arduino.  I had always heard great things about Tornado and noticed some of the Raspberry Pi community had success with it.  \n\nTornado Setup\n\nFirst things first, install Tornado on your Raspberry Pi:\n\n1.  Good thing to do before every install – update agt-get and installed packages\n\nsudo apt-get update\nsudo apt-get upgrade\n\n2.  Install easy_install and pip (which are Python package managers)\n\nsudo apt-get install python-pip python2.7-dev\n\n3.  Update your easy_install (and pip) package definitions\n\nsudo easy_install -U distribute\n\n4.  Now install Tornado using pip\n\nsudo pip install tornado\n\n5.  Follow the steps in this previous post to install Arduino on your Raspberry Pi\n\nsudo apt-get install arduino\nsudo usermod -a -G tty pi\nsudo usermod -a -G dialout pi\n\n6.  At this point might as well also install GPIO package as well, in case you need it later\n\nsudo pip install RPi.GPIO\n\n7.  Install another Python package to serial communication\n\nsudo apt-get install python-serial python3-serial\n\nTo make sure everything works, create a file named “server.py” containing the following code (taken from Tornado’s site), and run it from terminal using the command “python server.py”\n\nimport tornado.ioloop\nimport tornado.web\n\nclass MainHandler(tornado.web.RequestHandler):\n    def get(self):\n        self.write(\"Hello, world\")\n\napplication = tornado.web.Application([\n    (r\"/\", MainHandler),\n])\n\nif __name__ == \"__main__\":\n    application.listen(8080)\n    tornado.ioloop.IOLoop.instance().start()\n\nNow on a separate computer on the same network, navigate your browser to http://raspberrypi:8080 (or use the IP address for example 192.168.1.7:8080).  You should see “Hello, world” if everything goes right.\n\nAdding Websockets\n\nAdding websockets to your Tornado app is easy. Below is the modified version of server.py. It also includes support for command line arguments on line 8 (so you can run the program using “python server.py –port=8080”).\n\nimport tornado.httpserver\nimport tornado.ioloop\nimport tornado.options\nimport tornado.web\nimport tornado.websocket\n\nfrom tornado.options import define, options\ndefine(\"port\", default=8080, help=\"run on the given port\", type=int)\n\nclass IndexHandler(tornado.web.RequestHandler):\n    def get(self):\n        self.render('index.html')\n\nclass WebSocketHandler(tornado.websocket.WebSocketHandler):\n    def open(self):\n        print 'new connection'\n        self.write_message(\"connected\")\n\n    def on_message(self, message):\n        print 'message received %s' % message\n        self.write_message('message received %s' % message)\n\n    def on_close(self):\n        print 'connection closed'\n\nif __name__ == \"__main__\":\n    tornado.options.parse_command_line()\n    app = tornado.web.Application(\n        handlers=[\n            (r\"/\", IndexHandler),\n            (r\"/ws\", WebSocketHandler)\n        ]\n    )\n    httpServer = tornado.httpserver.HTTPServer(app)\n    httpServer.listen(options.port)\n    print \"Listening on port:\", options.port\n    tornado.ioloop.IOLoop.instance().start()\n\nAnd here is the corresponding index.html, which connects to the websocket server. I used KineticJS to quickly create a simple red circle on a canvas which listens from click events.  Be sure that your “ws://” url is correct.\n\n<!DOCTYPE HTML>\n<html>\n  <head>\n    <style>\n      body { margin: 0px; padding: 0px; }\n      canvas { border: 1px solid #9C9898; }\n    </style>\n    <script src=\"http://www.html5canvastutorials.com/libraries/kinetic-v4.2.0.js\"></script>\n    <script>\n\n      var socket = new WebSocket(\"ws://raspberrypi:8080/ws\");\n\n      socket.onopen = function(){\n        console.log(\"connected\");\n      };\n\n      socket.onmessage = function (message) {\n        console.log(\"receiving: \" + message.data);\n      };\n\n      socket.onclose = function(){\n        console.log(\"disconnected\");\n      };\n\n      sendMessage = function(message) {\n        socket.send(message);\n      };\n\n      var value = 0;\n\n      window.onload = function() {\n        var stage = new Kinetic.Stage({\n          container: \"container\",\n          width: 610,\n          height: 400\n        });\n\n        var layer  = new Kinetic.Layer();\n\n        var circle = new Kinetic.Circle({\n          x: 100,\n          y: 100,\n          radius: 10,\n          fill: \"red\",\n          stroke: \"black\",\n          strokeWidth: 4,\n          draggable: true\n        });\n\n        circle.on(\"mousedown\", function() {\n          value = value + 20;\n          console.log('sending: ' + value);\n          sendMessage(\"{value:\" + value + \"}\");\n        });\n\n        layer.add(circle);\n        stage.add(layer);\n      };\n\n    </script>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n  </body>\n</html>\n\nNow to test again start up your python script by executing “python server.py” in your terminal.  Next, direct your browser to http://raspberrypi:8080.  A couple of lines will show up in your terminal showing a connection is made.  In the browser you should see a small red circle and when you click it look for the following output in both your browsers console and your Raspberry Pi terminal (see screenshots).\n\nAdding Multiprocessing\n\nOne key difference between Node and Python, however is that Node is by nature highly asynchronous and event-driven, while Python is generally not.  With Node, you can easily set up events to be fired for both incoming web requests from clients as well as incoming serial data from the Arduino.  This is demonstrated in the previous post.  In a Python + Tornado setup, your program is in a single continuous IO loop waiting for web requests, which is initiated by the last line of every Tornado app:\n\ntornado.ioloop.IOLoop.instance().start()\n\nAny code placed after it won’t execute.  You’re allowed to interrupt this IO loop (see PeriodicCallback) to perform other tasks, for example talk to an Arduino over serial, but web requests will be blocked while other processing is going on.  Another option is to use a component of Tornado called Gen which can help you set up the asynchronous execution of a separate loop.  However, what I found to be the cleanest solution was to use Python’s own native “multiprocessing” module to spawn a separate process to perform the needed serial communication.\n\nYou’re probably thinking “That Node stuff was way easier. Isn’t multiprocessing a huge pain in the rear cause you have to deal with locks and concurrency and stuff like that?”  Well yes, but for what we’re trying to do it doesn’t get that complex, as you’ll see.  Also, Node’s asynchronicity is a double edged sword.  As your Node (JavaScript) code base grows, its easy to fall into the fiery pit known as callback hell. Seasoned JavaScript developers have ways to get around this, but I found it to be a nuisance.  Personally I find a larger Python program to be easier to trace through and maintain.  Ultimately, which language/programming style you go with will come down to your personal preference. Try out both and pick your poison.\n\nThere’s an excellent tutorial about Python multiprocessing by Doug Hellmann. It’s all I needed to get up and running with the module and I would urge anyone interested in the topic to check it out.\n\nInter-process communication is accomplished using the Queue data structure which comes with the multiprocessing module. Two queue’s are created, one for outgoing messages (taskQ) and one for incoming messages (resultQ). The queue’s are then passed to the spawned SerialProcess which sends anything in the taskQ to the Arduino over serial and puts any incoming data from the Arduino onto the resultQ. Tornado monitors the resultQ using PeriodicCallback.\n\nA complete round trip looks like this:\n\n1. Client sends a message to Tornado\n 2. Tornado sends it to SerialProcess using taskQ\n 3. SerialProcess sends it to the Arduino over serial\n 4. Arduino sends something back to SerialProcess over serial\n 5. SerialProcess sends it to Tornado using resultQ\n 6. Tornado sends it to all Clients\n\nBelow are all the code files (except index.html which remains the same as above). Here’s the final version of server.py:\n\n#!/usr/bin/python27\n\nimport tornado.httpserver\nimport tornado.ioloop\nimport tornado.web\nimport tornado.websocket\nimport tornado.gen\nfrom tornado.options import define, options\n\nimport time\nimport multiprocessing\nimport serialProcess\n\ndefine(\"port\", default=8080, help=\"run on the given port\", type=int)\n\nclients = []\n\nclass IndexHandler(tornado.web.RequestHandler):\n    def get(self):\n        self.render('index.html')\n\nclass WebSocketHandler(tornado.websocket.WebSocketHandler):\n    def open(self):\n        print 'new connection'\n        clients.append(self)\n        self.write_message(\"connected\")\n\n    def on_message(self, message):\n        print 'tornado received from client: %s' % message\n        self.write_message('got it!')\n        q = self.application.settings.get('queue')\n        q.put(message)\n\n    def on_close(self):\n        print 'connection closed'\n        clients.remove(self)\n\n################################ MAIN ################################\n\ndef main():\n\n    taskQ = multiprocessing.Queue()\n    resultQ = multiprocessing.Queue()\n\n    sp = serialProcess.SerialProcess(taskQ, resultQ)\n    sp.daemon = True\n    sp.start()\n\n    # wait a second before sending first task\n    time.sleep(1)\n    taskQ.put(\"first task\")\n\n    tornado.options.parse_command_line()\n    app = tornado.web.Application(\n        handlers=[\n            (r\"/\", IndexHandler),\n            (r\"/ws\", WebSocketHandler)\n        ], queue=taskQ\n    )\n    httpServer = tornado.httpserver.HTTPServer(app)\n    httpServer.listen(options.port)\n    print \"Listening on port:\", options.port\n    #tornado.ioloop.IOLoop.instance().start()\n\n    def checkResults():\n        if not resultQ.empty():\n            result = resultQ.get()\n            print \"tornado received from arduino: \" + result\n            for c in clients:\n                c.write_message(result)\n\n    mainLoop = tornado.ioloop.IOLoop.instance()\n    scheduler = tornado.ioloop.PeriodicCallback(checkResults, 10, io_loop = mainLoop)\n    scheduler.start()\n    mainLoop.start()\n\nif __name__ == \"__main__\":\n    main()\n\nA new file called serialProcess.py is as follows:\n\nimport serial\nimport time\nimport multiprocessing\n\nclass SerialProcess(multiprocessing.Process):\n\n    def __init__(self, taskQ, resultQ):\n        multiprocessing.Process.__init__(self)\n        self.taskQ = taskQ\n        self.resultQ = resultQ\n        self.usbPort = '/dev/ttyACM0'\n        self.sp = serial.Serial(self.usbPort, 115200, timeout=1)\n\n    def close(self):\n        self.sp.close()\n\n    def sendData(self, data):\n        print \"sendData start...\"\n        self.sp.write(data)\n        time.sleep(3)\n        print \"sendData done: \" + data\n\n    def run(self):\n\n        self.sp.flushInput()\n\n        while True:\n            # look for incoming tornado request\n            if not self.taskQ.empty():\n                task = self.taskQ.get()\n\n                # send it to the arduino\n                self.sp.write(task + \"\\n\");\n                print \"arduino received from tornado: \" + task\n\n            # look for incoming serial data\n            if (self.sp.inWaiting() > 0):\n                result = self.sp.readline().replace(\"\\n\", \"\")\n\n                # send it back to tornado\n                self.resultQ.put(result)\n\nFinally, here’s the Arduino program which simply listens for incoming data and returns it:\n\n#define LED_PIN 13\n\nint msgByte= -1;         // incoming byte\nconst int msgSize = 50;  // max message size\nchar msgArray[msgSize];  // array for incoming data\nint msgPos = 0;          // current position\n\nvoid setup() {\n    Serial.begin(115200);\n    pinMode(LED_PIN, OUTPUT);\n}\n\nvoid loop() {\n    handleSerial();\n}\n\nvoid handleSerial() {\n  if (Serial.available() > 0) {\n        digitalWrite(LED_PIN, HIGH);\n    msgByte = Serial.read();\n\n    if (msgByte != '\\n') {\n      // add incoming byte to array\n      msgArray[msgPos] = msgByte;\n      msgPos++;\n    } else {\n      // reached end of line\n      msgArray[msgPos] = 0;\n\n      // here the message is processed\n      // for now just send it back over serial\n      Serial.println(msgArray);\n\n      // reset byte array\n      for (int c = 0; c < msgSize; c++)\n        msgArray[c] = ' ';\n\n      msgPos = 0;\n      digitalWrite(LED_PIN, LOW);\n    }\n  }\n}\n\nTest it out as shown above and you should now see the following output (click to enlarge):","projects":[],"links":{"body":["http://www.tornadoweb.org/","http://www.raspberrypi.org/","http://nodejs.org/","http://arduino.cc/","https://niltoid.com/blog/raspberry-pi-setup/","https://niltoid.com/blog/raspberry-pi-arduino/","https://niltoid.com/blog/web-controlled-rgb-led-pixels/","http://kineticjs.com/","https://niltoid.com/blog/raspberry-pi-arduino-tornado/torduinoterm1.png","http://www.tornadoweb.org/documentation/ioloop.html","http://www.tornadoweb.org/documentation/gen.html","https://niltoid.com/blog/raspberry-pi-arduino-tornado/tornado1.jpg","http://callbackhell.com/","http://pymotw.com/2/multiprocessing/index.html","http://en.wikipedia.org/wiki/Inter-process_communication","https://niltoid.com/blog/raspberry-pi-arduino-tornado/torduinotermfinal.png"]},"media":[{"url":"https://niltoid.com/blog/raspberry-pi-arduino-tornado/img_20130215_213350.jpg","alt":""},{"url":"https://niltoid.com/blog/raspberry-pi-arduino-tornado/torduinoterm1.png","alt":"torduinoTerm"},{"url":"https://niltoid.com/blog/raspberry-pi-arduino-tornado/tornado1-800x12001.jpg","alt":""},{"url":"https://niltoid.com/blog/raspberry-pi-arduino-tornado/torduinotermfinal.png","alt":"torduinoTermFinal"}]},{"slug":"web-controlled-rgb-led-pixels","title":"Raspberry Pi + Arduino + Node = Home Automation","date":"2013-02-09","summary":"Controlling addressable RGB LEDs from a browser-based mixer through a Raspberry Pi, Node, Socket.IO and an Arduino.","url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/","tags":["tutorial","Raspberry Pi","Arduino","Node","Socket.IO","KineticJS","LEDs"],"skills":["real-time sync","hardware integration","Canvas"],"themes":["robots-hardware"],"dek":"","bodyText":"After figuring out how to set up the Raspberry Pi and how to communicate between a Raspberry Pi and an Arduino, I wanted to try a simple home-automation project that incorporated several really awesome and useful technologies:\n\n– Raspberry Pi\n– Node\n– Socket.IO\n– Canvas with KineticJS\n– Arduino\n– RGB LED Pixels\n\nThe following diagram shows how all this tech is arranged.  \n\nThis is by no means the only way to do home-automation, but its a fun project if you don’t mind programming, and there are a lot of advantages to using these particular tools.  Having a browser based interface allows you to work the controls from virtually any computer or mobile device.  Canvas gives you the ability to create a rich interactive experience for the end-user.  KineticJS makes it incredibly easy to make canvas animations.  The Raspberry Pi gives you the benefit of a fully functional web server and allows the project to be portable.  Node makes developing that web server as well as serial communication with the Arduino quick and easy.  Websockets and Socket.IO allow the server to easily push updates to all clients in real time, so if I tweak a slider, everyone viewing the control panel sees me move it.  Finally the Arduino gives us an easy way to control the physical world and access to countless libraries including one that helps to work with the RGB LED Pixels .\n\nHere is a video of the whole thing in action:\n\nIn my previous tests, Firmata was a great choice for integrating the Pi and Arduino since it simplified the code base – instead of writing a C program for the Arduino, the Arduino was controlled directly from my Node program.  In this case however, I opted to leverage this Adafruit Arduino library to work with the RGB LED Pixels.  So it made more sense to write a separate Arduino sketch which incorporates this lib and communicates with Node over serial.  Couple of things to note:\n\n1. Arduino libraries go in this location:\n    /usr/share/arduino/libraries/\n\n2. Node serial communication can be done using this package\n    sudo npm install -g serialport\n\n3. Optional: Since the Arduino IDE is quite slow on the Pi, Ino is a great option for building and uploading arduino code from the command line.\n\nHere is our holiday tree outfitted with RGB LED Pixels from Adafruit.com\n\nFrom another angle you can see the attached Raspberry Pi and Arduino (in the dark)\n\nA clearer daytime pic of the setup. Breadboard with BBB Arduino Clone –> USB BUB –> male-to-male mini-A USB adapter –> Raspberry Pi\n\nThe Raspberry Pi is running a Node web server which communicates with clients using Socket.IO. Here it is in its entirety. For the canvas and arduino code, see the Github repo below.\n\nWhen on the same network as the Pi, navigating a browser to http://raspberrypi:8080 brings up this canvas based control panel. I used KineticJS to make this happen faster\n\nNext, I’d like to take this project further by having a line of communication coming back from the Arduino to the canvas front-end.  When multiple clients are looking at the control panel and one user moves the sliders, everyone should see them move in close to real time.\n\nIn addition to my desktop browser, I tried this out from my Android device (LG Nexus 4 running Chromium).  I was disappointed to find that the animation is clunky and jumpy, and touch control is inaccurate.  I’ve heard that unless they’re very simple, canvas animations require extensive optimization to work in mobile browsers.  I have friends that are struggling with similar issues, so hopefully there will be some advancement in this area on mobile browsers to make canvas truly universal.\n\nThe source code for this project is available here on Github.","projects":[{"name":"WebControlledRgbPixels","repo":"https://github.com/asaeed/WebControlledRgbPixels"}],"links":{"video":"https://www.youtube.com/watch?v=N39lwZe4kwQ","body":["https://niltoid.com/blog/raspberry-pi-setup/","https://niltoid.com/blog/raspberry-pi-arduino/","http://www.raspberrypi.org/","http://nodejs.org/","http://socket.io/","http://kineticjs.com/","http://arduino.cc/","http://www.adafruit.com/products/738","https://niltoid.com/blog/web-controlled-rgb-led-pixels/screen-shot-2013-02-05-at-10.29.26-pm.png","https://github.com/adafruit/Adafruit-WS2801-Library","https://github.com/voodootikigod/node-serialport","http://inotool.org/quickstart","https://niltoid.com/blog/web-controlled-rgb-led-pixels/img_20130105_142453.jpg","https://github.com/asaeed/WebControlledRgbPixels"]},"media":[{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/screen-shot-2013-02-05-at-10.29.26-pm.png","alt":""},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/img_20121223_032817.jpg","alt":""},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/img_20121223_032021.jpg","alt":""},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/img_20130105_142453.jpg","alt":""},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/nodeonpi.png","alt":"nodeOnPi"},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/ledmixer.png","alt":"ledMixer"},{"url":"https://niltoid.com/blog/web-controlled-rgb-led-pixels/img_20121223_033341_1.jpg","alt":""}]},{"slug":"raspberry-pi-arduino","title":"Raspberry Pi + Arduino: Getting Started","date":"2013-01-09","summary":"Combining a Raspberry Pi’s server capabilities with an Arduino’s hardware interfaces, then controlling the Arduino from Node over serial.","url":"https://niltoid.com/blog/raspberry-pi-arduino/","tags":["tutorial","Raspberry Pi","Arduino","Node","Firmata"],"skills":["serial communication","hardware integration"],"themes":["robots-hardware"],"dek":"","bodyText":"The Raspberry Pi kind of looks like an Arduino replacement as far as it’s physical appearance.  At first glance, it’s specs are much more impressive for the same price point as an Arduino.  However, it is by no means an “Arduino killer”.  You could certainly swap out one for the other in some simple use cases.  However the two devices have very different capabilities, and I find that they actually complement each other quite well when combined.   \n \nPictured here left to right: Raspberry Pi, Arduino Mega, Arduino NG, Arduino Pro Mini\n \nHere is one important reason the Arduino is still essential, from the author of Getting Started with Raspberry Pi:\n \nWhen you have a problem that requires exact control in real time, such as a controller for a 3D printer.  Raspbian is not a Real Time operating system, and programs can’t necessarily depend on the same “instruction per clock cycles” rigor of a microcontroller.\n \nHere are some other ways the Arduino has a leg up:\n \n– Supports analog pins required for many types of sensors and actuators\n– Supports a larger number of digital pins\n– Includes PWM pins (pulse width modulation) used for some types of sensors and actuators\n– Lower power consumption – Pi is about 7x the power consumption – ie, Arduino will last about 7x longer on battery\n– Some Arduino clones are cheap as fudge\n– Lots of parts made to integrate directly with Arduino, such as sheilds.\n– Lots of code libraries exist for the Arduino\n \nAs for the Pi, the advantages are pretty obvious:\n \n– Still the most processing power for your money\n– Ability to easily program and drive graphics\n– Integration with computer peripherals\n– Access to tons of open source Linux and Python tools\n– Easier to use for advanced network functionality (VNC on to it, run a websocket server, etc)\n– Much more…\n \nWhen connected to each other, the two devices can be use for the tasks they are best at. The Arduino for controlling hardware and the Pi for controlling software. There are a number of ways for them to communicate:\n\n1.  They can have their own separate programs running and communicate over Serial, I2C, or SPI (only tried Serial so far)\n \n2.  You can use something called “firmata” to control a connected Arduino directly from Node or Python on the Pi  (eg: Node Firmata)\n \nThe advantage of #1 is that you can still use libs written for Arduino to interface with hardware more efficiently.  The advantage of #2 is that you have just a single code base to maintain, without the need for context switching.  A HUGE plus with any method is that you can program your Arduino by VNC’ing into the Pi.  this is great if your setup is mounted somewhere inaccessible like on the ceiling or inside a casing.\n\nIt’s hard to see what’s going on in the above images.  On the breadboard is an Arduino clone called the BBB from ModernDevice.com (white).  To cut it’s cost, it doesn’t have an on-board USB port, so to give it USB I use an component called a USB BUB (red).  Then there’s a male A to male mini-A USB adapter (black).  Finally I can connect the Raspberry Pi (green).\n\nInstall Arduino\n\nAnyways, enough talking and more doing.  To get started, install the Arduino IDE on the Raspberry Pi:\n\nsudo apt-get update\nsudo apt-get install arduino\n\nYou’ll need to do this before running the Arduino IDE.\n\nsudo usermod -a -G tty pi\nsudo usermod -a -G dialout pi\n\nNow you can launch Arduino IDE while running X11 by going to Start menu -> Programming -> Arduino IDE.  If your Pi is on WiFi, even better – VNC into it for remote and wireless control.  Keep in mind, you now have slightly more power consumption which may require you to use a power adapter with more amperage.  I was able to power a Pi, hooked up to an Arduino, hooked up to 25 addressable RGB LED pixels using a 5V 1.2A phone charger with no problem.\n\nInstall Node\n\nI decided to start out programming on the Pi a little differently.  The more common way is to use Python which comes pre-installed.  I’ve recently been exploring Node.js and decided to see how it plays with the Pi.\n\nInstall Node.js with the following commands:\n\nwget http://nodejs.org/dist/v0.8.17/node-v0.8.17.tar.gz\ntar -zxf node-v0.8.17.tar.gz\ncd node-v0.8.17\n./configure\nmake\nsudo make install\n\nNext create a file as follows to test (must use 0.0.0.0 instead of 127.0.0.1):\n\nvar http = require('http');\nhttp.createServer(function (req, res) {\n    res.writeHead(200, {'Content-Type': 'text/plain'});\n    res.end('Hello World\\n');\n}).listen(8080, \"0.0.0.0\");\nconsole.log('Server running at http://0.0.0.0:8080/');\n\nTo test, open up a browser on a computer which is on the same network as the Pi, and navigate to http://raspberrypi:8080 (or the IP address for example http://192.168.1.7:8080).  You should see “Hello World”.\n\nNow that we have Arduino and Node working individually, lets get them working together.\n\nNode + Arduino + Firmata\n\nAs mentioned above, Firmata is an interesting way to control the Arduino and get out of writing any C code. It wouldn’t be my preferred method since you lose out on some amazing open source Arduino libraries, but it’s a really easy way to control an Arduino on a very basic level.\n\n1. Install Node and Arduino as explained above\n\n2. Run Arduino IDE, open Examples->Firmata->StandardFirmata, and upload it to your Arduino board.\n\n3. From terminal install the package firmata for Node:\n\nsudo npm install -g firmata\n\n4. Create a file called app.js containing the following code\n\n/**\n * Sample script to blink LED 13\n */\n\nconsole.log('blink start ...');\n\nvar ledPin = 13;\nvar firmata = require('/usr/local/lib/node_modules/firmata');\nvar board = new firmata.Board('/dev/ttyUSB0', function(err) {\n    if (err) {\n        console.log(err);\n        return;\n    }\n    console.log('connected');\n    console.log('Firmware: ' + board.firmware.name + '-' + board.firmware.version.major + '.' + board.firmware.version.minor);\n\n    var ledOn = true;\n    board.pinMode(ledPin, board.MODES.OUTPUT);\n\n    setInterval(function(){\n        if (ledOn) {\n            console.log('+');\n            board.digitalWrite(ledPin, board.HIGH);\n        }\n        else {\n            console.log('-');\n            board.digitalWrite(ledPin, board.LOW);\n        }\n        ledOn = !ledOn;\n    },500)\n\n});\n\n5. Run the app as sudo:\n\nsudo node app.js\n\nIntegrate Socket.io\n\nSo far, we’ve created a simple Node server script that controls the Arduino. How about giving it a front-end? That way you can interact with your Arduino using a web browser. Just for kicks, why not use websockets since that’s a nice and easy-to-work-with feature Node offers. Socket.io makes it even easier. Simply install Socket.io using the following command:\n\n    sudo npm install -g socket.io\n\nThis is what I used for index.html:\n\n<html>\n    <head>\n        <title>web led switch</title>\n    </head>\n    <body>\n        <div>\n            <p>\n                <button id=\"switchButton\">turn on</button>\n            </p>\n        </div>\n        <div>\n            <ul id=\"messages\">\n            </ul>\n        </div>\n        <script src=\"socket.io/socket.io.js\"></script>\n        <script src=\"http://code.jquery.com/jquery-1.8.0.min.js\"></script>\n\n        <script>\n            $(function(){\n                var socket = io.connect('http://raspberrypi:8080');\n\n                socket.on('connect', function() {\n                    $('#messages').append('<li>Connected to the server.</li>');\n                });\n\n                socket.on('message', function(message) {\n                    $('#messages').append('<li>' + message + '</li>');\n                });\n\n                socket.on('disconnect', function() {\n                    $('#messages').append('<li>Disconnected from the server.</li>');\n                });\n\n                $('#switchButton').bind('click', function() {\n                    var message = $('#switchButton').text();\n                    socket.send(message);\n                    $('#messages').append('<li>me: ' + message + '</li>');\n\n                    if (message == 'turn on')\n                        $('#switchButton').text('turn off');\n                    else\n                        $('#switchButton').text('turn on');\n                });\n            });\n        </script>\n    </body>\n</html>\n\nThis is app.js:\n\nvar app = require('http').createServer(handler),\n    io = require('/usr/local/lib/node_modules/socket.io').listen(app),\n    fs = require('fs'),\n    firmata = require('/usr/local/lib/node_modules/firmata'),\n    board = new firmata.Board('/dev/ttyUSB0', arduinoReady);\n\nvar ledPin = 13;\n\nfunction arduinoReady(err) {\n    if (err) {\n        console.log(err);\n        return;\n    }\n    console.log('Firmware: ' + board.firmware.name\n      + '-' + board.firmware.version.major\n      + '.' + board.firmware.version.minor);\n\n    var ledOn = true;\n    board.pinMode(ledPin, board.MODES.OUTPUT);\n}\n\napp.listen(8080);\nconsole.log(\"Listening on http://raspberrypi:8080...\");\n\n// directs page requests to html files\n\nfunction handler (req, res) {\n  fs.readFile(__dirname + '/index.html',\n  function (err, data) {\n    if (err) {\n      res.writeHead(500);\n      return res.end('Error loading index.html');\n    }\n\n    res.writeHead(200);\n    res.end(data);\n  });\n}\n\n// this handles socket.io comm from html files\n\nio.sockets.on('connection', function(socket) {\n    socket.send('connected...');\n\n    socket.on('message', function(data) {\n        if (data == 'turn on') {\n            console.log('+');\n            board.digitalWrite(ledPin, board.HIGH);\n            socket.broadcast.send(\"let there be light!\");\n        }\n        if (data == 'turn off') {\n            console.log('-');\n            board.digitalWrite(ledPin, board.LOW);\n            socket.broadcast.send(\"who turned out the light?\");\n        }\n        return;\n    });\n\n    socket.on('disconnect', function() {\n        socket.send('disconnected...');\n    });\n});","projects":[],"links":{"body":["http://books.google.com/books?id=qKQcXBpWXPAC","https://github.com/jgautier/firmata","http://shop.moderndevice.com/products/bbb-kit","http://shop.moderndevice.com/products/usb-bub","http://www.adafruit.com/products/738","http://nodejs.org/","http://socket.io/"]},"media":[{"url":"https://niltoid.com/blog/raspberry-pi-arduino/img_20130105_155212.jpg","alt":""},{"url":"https://niltoid.com/blog/raspberry-pi-arduino/img_20130105_142231.jpg","alt":""},{"url":"https://niltoid.com/blog/raspberry-pi-arduino/img_20130105_142453.jpg","alt":""}]},{"slug":"raspberry-pi-setup","title":"Raspberry Pi Setup","date":"2013-01-01","summary":"Getting a Raspberry Pi running reliably, then setting up headless access and a Node server for further experiments.","url":"https://niltoid.com/blog/raspberry-pi-setup/","tags":["tutorial","Raspberry Pi","Raspbian","Linux"],"skills":["Linux administration","remote access"],"themes":["robots-hardware"],"dek":"","bodyText":"I ordered a Raspberry Pi (Model B Rev 2) back in March and it finally arrived in November.  Since, I’ve been exploring the capabilities of this $35 computer-on-a-chip.  For its price and size it packs a very formidable punch.  From the raspberrypi.org FAQ:\n\n… graphics capabilities are roughly equivalent to Xbox 1 level of performance. Overall real world performance is something like a 300MHz Pentium 2, only with much, much swankier graphics.\n\nTurn it into a arcade game console, a media center,  a portable music player, pair it with an Arduino, or simply use it as a computer for word processing and internet browsing, the possibilities are endless.\n\nUp and Running\n\nI found the Adafruit tutorials to be helpful for getting started.  First off, setting up the SD card and the initial config…\n\n1. Tutorial to setup SD card\n\n2. Tutorial to do rasp-config\n\nIn addition, also change_locale as US – UTF8 – UTF8\nand configure_keyboard to make it American layout\n\nNow at this point the Pi started inexplicably crashing after 5-10 minutes of being on. Looking online, I was disappointed to learn that some others experienced this and the unit could be from a faulty batch.  The next day I decided to give it another shot, this time removing the Pi from this case purchased from RS Online.  That seemed to fix the issue and I have had no crashes since!  It appears the case was causing the Pi to overheat and crash.  Since I’ve discarded the case, I’ve been able to run the Pi without fail for days at a time.\n\n“Headless” mode\n\nThere are a couple ways to control your Pi remotely and free up the monitor and keyboard it is connected to.  \n\na) SSH access using Putty is possible by default.  The only setting needed is the Host Name for which you can use the Raspberry Pi’s IP address or “raspberrypi”.  Once prompted for login/password, use “pi”/”raspberry”.\n\nb) VNC into an X11 session using these instructions.\n\nNote that if you configured to launch X11 on startup, these instructions need a slight modification – use :1 instead of :0\n\nGit installation and Dropbox integration\n\nDropbox Uploader is a great tool written in bash which makes it easy to automate reading from and writing to Dropbox. \n\na) Install Git using the command: sudo apt-get install git-core\n\nb) To install Dropbox Uploader script\n\ncd /usr/local/bin\nsudo git clone https://github.com/andreafabrizi/Dropbox-Uploader.git dropbox\n\nc) optional: delete everything except the file dropbox_uploader.sh\n\nd) run dropbox_uploader.sh and follow instructions\n\nNow you can call dropbox_uploader.sh from anywhere.\n\nSetup WiFi\n\nTo set up a WiFi USB Adapter, modify file /etc/wpa_supplicant/wpa_supplicant.conf by appending this after update_config=1\n\nnetwork={\n  ssid=\"YOUR_SSID\"\n  scan_ssid=1\n  psk=\"YOUR_PASSPHRASE\"\n  proto=RSN\n  key_mgmt=WPA-PSK\n  pairwise=CCMP\n  auth_alg=OPEN\n}\n\nKey:\n\nssid: your wifi name\nscan_ssid: value of 1 means broadcast and value of 2 means hidden (suggest value of 1)\npsk: your wifi password\nproto: your choice of RSN or WPA. RSN is WP2 and WPA is WPA1. (most config is RSN)\nkey_mgmt: your choice of WPA-PSK or WPA-EAP (pre-shared or enterprise respectively)\npairwise: your choice of CCMP or TKIP ( WPA2 or WPA1 respectively)\nauth_alg: OPEN option is required for WPA and WPA2 (other option, SHARED & LEAP)\n\nKeeping the Screen On\n\nWhen in X Windows, the screen goes blank after 10 min and needs to be “woken”.  There are many suggestions in the forums but most failed to keep my Raspi awake.  This solution which is a sort of attack on all fronts finally worked out.  Here’s an excerpt: \n\nApproach 1\n\nOn Pi 1 I don’t want screensaver – but don’t want to autorun x. When I start up x I do it manually and it references /home/pi/.xinitrc so managed to stop the screensaver on there by using information from http://raspberrypi.stackexchange.com/qu … oing-blank\n\napt-get install x11-xserver-utils\n\nNow open up your ~/.xinitrc file (if you don’t have one then create it) and enter this:\n\nxset s off # don’t activate screensaver\nxset -dpms # disable DPMS (Energy Star) features.\nxset s noblank # don’t blank the video device\n\nApproach 2\n\nOn Pi 2 I have it auto-logging in and auto-starting to x using the raspi-config script use of lightdm. This seems to ignore /home/pi/.xinitrc\n\nFor this I used belt and braces.\nThe Belt:\n\nEdit /etc/lightdm/lightdm.conf\n\n[SeatDefaults]\nxserver-command=X -s 0 -dpms\n\nThe Braces:\n\nStep 1. Do as per Approach 1\n\nStep 2. Run the .xinitrc as an autostart script\n\ncd ~/.config\nmkdir autostart\ncd autostart\nvi screensaver.desktop\n\npress “i” to insert, paste the following lines, then press the esc button and then “:wq” to save:\n\n[Desktop Entry]\nType=Application\nExec=/home/pi/.xinitrc","projects":[],"links":{"body":["http://www.raspberrypi.org/","http://www.raspberrypi.org/faqs","http://adafruit.com/","http://learn.adafruit.com/adafruit-raspberry-pi-lesson-1-preparing-and-sd-card-for-your-raspberry-pi","http://learn.adafruit.com/adafruits-raspberry-pi-lesson-2-first-time-configuration","http://raspberrypi.rsdelivers.com/product/rs/raspberry-pi-type-b-case-white/casewht.aspx","http://elinux.org/RPi_VNC_Server","http://www.andreafabrizi.it/?dropbox_uploader","http://www.raspberrypi.org/phpBB3/viewtopic.php?f=63&t=17797"]},"media":[{"url":"https://niltoid.com/blog/raspberry-pi-setup/raspi1.jpg","alt":"Raspberry Pi Model B connected to power, video and USB cables"},{"url":"https://niltoid.com/blog/raspberry-pi-setup/img_20121210_133557.jpg","alt":"Raspberry Pi inside its white case"},{"url":"https://niltoid.com/blog/raspberry-pi-setup/img_20121210_141527.jpg","alt":"Raspberry Pi with the case removed"}]},{"slug":"ruby-on-rails-on-ubuntu-on-virtualbox","title":"Ruby on Rails on Ubuntu on VirtualBox","date":"2012-12-21","summary":"Setting up Ruby on Rails inside an Ubuntu virtual machine, including shared folders, networking and the JavaScript runtime needed to start a Rails app.","url":"https://niltoid.com/blog/ruby-on-rails-on-ubuntu-on-virtualbox/","tags":["tutorial","Ruby on Rails","Ruby","Ubuntu","VirtualBox"],"skills":["development environments"],"themes":[],"dek":"","bodyText":"I started exploring Ruby on Rails for a potential client project which never kicked off.  These are the steps I took to set up RoR on Ubuntu running on VirtualBox.\n\n1.  Install VirtualBox 4.1.20\n\nguide: https://www.virtualbox.org/wiki/Downloads\n\n2.  Install Ubuntu 12.04\n\nguide: http://www.psychocats.net/ubuntu/virtualbox\n\nFor resizing, copy/paste, share folders…\n   a) “Install Guest Additions”, sometimes it doesn’t work and you have to go to /media/VBOXADDITIONS_… and run\n       sh VBoxLinuxAdditions.run\n   b) then enable clipboard in settings as Bidirectional\n   c) then restart the instance.\n\nFor it’s own IP address\n   a) go to settings->network and select Bridged Adapter\n   b) if already running instance, reset network by running\n     sudo /etc/init.d/networking restart\n\n3.  Install Ruby on Rails using rvm\n\nguide: https://www.digitalocean.com/community/articles/how-to-install-ruby-on-rails-on-ubuntu-12-04-lts-precise-pangolin-with-rvm\n\n 4.  Run this to make sure rvm runs every time you open a new terminal\n\n echo ‘[[ -s “$HOME/.rvm/scripts/rvm” ]] && source “$HOME/.rvm/scripts/rvm”‘ >> ~/.bashrc\n\n…or else this needs to be run when new terminal is opened\n source ~/.rvm/scripts/rvm\n\n 5.  as suggested on http://rubyonrails.org/download, create a skeleton site:\n\nrails new ~/code/ror/HelloRoR\n cd ~/code/ror/HelloRoR\n rails server\n\n…however this gives the following error:\n Could not find a JavaScript runtime.\n\n6.  To resolve: sudo apt-get install nodejs\n\n7.  open a browser and go to http://localhost:3000\n\n8.  ctrl-c to stop server (don’t just close term window or else process must be killed manually before restarting server)\n\n9.  gedit-gmate as code editor\n\nhttp://kibyegon.wordpress.com/2011/11/15/using-gedit-as-a-ruby-ide/\n http://blog.sudobits.com/2012/03/11/gedit-plugins-for-ruby-on-rails/\n\n10. mysql\n\nsudo apt-get install mysql-server mysql-client\nsudo apt-get install libmysql-ruby libmysqlclient-dev\ngem install mysql2\n\n11.  Download mysql workbench for ubuntu 12.04\n\n(later try to use workbench on host windows 7 machine and connect to mysql server on ubuntu, but it’s more involved)\n\nFrom terminal, run\n mysql-workbench\n\n12. Create a RoR project which connects to MySQL\n\nmkdir HelloRoRMySQL\ncd HelloRoRMySQL\nrails new HelloRoRMySQL -d mysql\n\n13. useful generate scaffolding commands:\n\nrails generate scaffold User userName:string fbId:bigint\n   – since bigint is not accepted, go into db/migrate open the file and change\n     t.bigint :fbId  to  t.column :fbId, :bigint\n rake db:migrate\n rails destroy scaffold User\n rails g migration add_bio_to_user bio:text\n   – this doesn’t modify views\n\n14. to test\n\nhttp://localhost:3000/users\n http://localhost:3000/users.json","projects":[],"links":{"body":["https://www.virtualbox.org/wiki/Downloads","http://www.psychocats.net/ubuntu/virtualbox","https://www.digitalocean.com/community/articles/how-to-install-ruby-on-rails-on-ubuntu-12-04-lts-precise-pangolin-with-rvm","http://rubyonrails.org/download","http://localhost:3000/","http://kibyegon.wordpress.com/2011/11/15/using-gedit-as-a-ruby-ide/","http://blog.sudobits.com/2012/03/11/gedit-plugins-for-ruby-on-rails/","http://localhost:3000/users","http://localhost:3000/users.json"]},"media":[]},{"slug":"netduino-robot-drummer","title":"Netduino Robot Drummer","date":"2012-08-25","summary":"A robotic drummer that plays beat patterns with solenoids and listens with a knock sensor, using Netduino timers and threads to keep time.","url":"https://niltoid.com/blog/netduino-robot-drummer/","tags":["tutorial","Netduino","C#",".NET Micro Framework","solenoids"],"skills":["motor control","multithreading","signal processing"],"themes":["robots-hardware","sound-visuals"],"dek":"","bodyText":"The Netduino is Microsoft’s answer to the Arduino.  It runs using the .NET Micro Framework (.NETMF) which means you can program it using C# within Visual Studio and with whole bunch of useful .NET standard libraries at your disposal.  It is a breeze to setup and get started. \n\n The goal of this project is to construct a robotic drummer using a microcontroller as the robot brain and a few solenoids as actuators that make drum sounds.  I had a Netduino lying around and it was the perfect choice for this project since multi-threading is supported natively. This helps to simplify the code base, since when I want to activate a solenoid, I can simply spawn a thread which turns on the solenoid, waits a moment and then turns off the solenoid, and I don’t have to worry about this delay effecting the timing of subsequent drum hits.  I can even trigger a drum roll or complicated riff if I want. Accomplishing the same task on an Arduino without the help of multi-threading is not too difficult either, but would take some extra effort, so this was a good excuse to try out the Netduino and it’s capabilities.\n\n I eventually was able to leverage the .NETMF Threading and Timer classes for even more.  Here is a great reference on the basics of multithreading on .NETMF.  I have each Beat in a BeatPattern running on a separate “Timer” thread.  The KnockDetector also runs on a separate thread so the (relatively) heavy number crunching doesn’t interfere with the timing of the drums.\n\n Playing a Beat Pattern\n\n I wanted to use solenoids to produce drum sounds by banging on things.  One of the most frustrating things about the 12V push solenoids i had was that they had no frame and return spring.  To make them usable, I had to construct custom frames out of metal and find some really weak springs to spring them back to their starting position after they’ve struck a beat.  I purchased a variety pack of 100′s of springs but none of them were weak enough!  I finally found some that were sold individually at a local hardware store, but i had to “weaken” them further.  The strength of a spring depends on the thickness of the wound metal and also the radius of the winding, so stretching them out to increase that radius works.  Lacking a frame also made mounting your solenoids a challenge.  It is much easier to just purchase solenoids that include a frame and return spring.  You also end up with something less rusted and ugly (good thing they’ll be out of sight eventually)\n\nThe circuit for each solenoid resembled the following diagram, which comes courtesy of this Bildr page.\n\nThere are a few differences in my circuit.  My power source comes out of the netduino 5V pin, so its weaker than the 12V used in this diagram.  I also used a schottky diode instead of the zener diode pictured and a 1kΩ  resistor instead of a 2.2kΩ resistor.  If anyone has any insight on whether I’d be better off modifying my circuit, I would love to hear your suggestions, please do post a comment.\n\nOn the software side, I created a BeatPattern class which, among other things, consists of an array of Beats.  Each beat has its own thread which I set up using the .NETMF Timer library.  At the beginning of a measure, the main program calls BeatPattern.update() which tells each Beat in the pattern to get ready to play it’s corresponding solenoid at the right moment, depending on the tempo.\n\n Here is an early version of the beat making portion of the project:\n\nKnock Detection\n\n Hardware-wise, knock detection was quite simple.  A piezoelectric buzzer can easily be used as a sort of knock or vibration or movement sensor if it’s correctly hooked up to an input pin on the microcontroller.  Below is a diagram for the arduino.cc tutorial on this topic.\n\nThe software side of knock detection was more tricky.  I set up a new thread to just listen for values coming from the knock sensor every 10 ms.  Since this is an analog sensor, it has to be hooked up to an analog pin on the Netduino and will give you a continuous value (as opposed to a discrete 1 or 0).  This means you end up getting a string of numbers for each hit.  For example a single knock may give you the following values:\n\n0 - 0 - 0 - 55 - 127 - 358 - 82 - 0 - 0 - 0\n\nIt looks like you can just take the highest numbers between 0′s to get your knock’s timing.  This is true in some cases, however, a couple of knocks in quick succession may give you something like:\n\n0 - 0 - 55 - 127 - 358 - 82 - 20 - 101 - 530 - 222 - 71 - 0 - 0\n\nSo to get both distinct knocks, I keep track of whether the current reading is on a “rising edge” or a “falling edge”.  If rising and current value is starting to fall, the last reading was the peak.  As always, see the code which is linked below for more details.\n\n Finally I made a custom class called Knock with members “interval” and “volume”.  Volume is simply the peak number from above, and to calculate the interval I used a Stopwatch class (copy it into a code file and include it in your project).  Now I can store all my peaks in an array of Knocks for interpretation later.\n\n Here are all the parts of this project prototype.  The 3 solenoids, the breadboard circuit, the microcontroller, and of course the box which will house everything and has the piezoelectric buzzer installed on top.  I also added a button because I’m considering using it as a very simple user interface to tell the drums when to start and stop.\n\nTempo Extraction\n\nUnless your knocks are in a steady “4 on the floor” pattern (think techno), determining the user’s tempo is a difficult task.  Sometimes called “Beat Detection”, Tempo Extraction is a complicated process which is the subject of many scientific papers.  It involves a lot of number crunching and can bring your microcontroller, which lacks a powerful processor, to a grinding halt, so to speak.\n\nDrawing clues from research papers I found online, I wrote a very simplified version of a Tempo Extraction algorithm which performs well and yields a fairly reliable beat interval reading.  It only works for the 4/4 meter which simplifies the task quite a bit.  Keep in mind, this means there are 4 beats in a measure.  A beat interval is the time between 2 consecutive beats.  The beat interval value is computed in milliseconds and can easily be converted to a BPM (beats per minute) by dividing 60K by it.  To convert back, again, divide 60K by your BPM value.\n\nBPM = 60000 / BeatInterval\n\nThe rational behind the Tempo Extraction algorithm is that beats in a 4/4 pattern usually fall on a whole, half, quarter, or eighth note.  So consecutive beats should generally have one of these intervals between them.  I compare each beat to it’s previous beat, two beats ago, and three beats ago, then “normalize” the intervals by either dividing by 2 or multiplying by 2 since all the intervals should be multiples by this theory.\n\nThen I perform the following steps on the array:\n\n1.  Sort the array of intervals\n2.  Find the median\n3.  Throw out the outliers\n4.  Take the average of what’s left\n\nThis gives me a pretty decent beat interval value.  See the code linked below for the nitty gritty, though keep in mind its a work in progress.   I would love to hear from anyone who has experience with any of the techniques described above and can suggest an improvements or alternative methods!\n\nhttps://github.com/asaeed/RobotDrummer\n\n On a side note, I noticed one shortcoming of .NETMF is that it lacks support for generics, which means a lot of nice built in functions – like Sort() on an ArrayList – are just missing.  I used extension methods to make my own algorithms on an ArrayList of integers.  But extension methods don’t work out of the box, there’s a little trick I learned thanks to this guy to get them working.","projects":[{"name":"RobotDrummer","repo":"https://github.com/asaeed/RobotDrummer"}],"links":{"video":"https://www.youtube.com/watch?v=IkGl75cgbd0","body":["https://niltoid.com/blog/netduino-robot-drummer/netduino.jpg","http://netduino.com/","http://ghadzhigeorgiev.wordpress.com/2011/09/08/multithreading-with-netduino-and-net-microframework-part-1/","https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144935.jpg","http://wiki.bildr.org/index.php/Controlling_a_solenoid_(TIP120_Arduino)","http://wiki.bildr.org/images/thumb/0/05/SolenoidArduinoTip120.png/450px-SolenoidArduinoTip120.png","https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144715.jpg","http://arduino.cc/en/Tutorial/Knock","http://arduino.cc/en/uploads/Tutorial/knock_bb.png","http://forums.netduino.com/index.php?/topic/97-systemdiagnosticsstopwatch-class/","https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144919.jpg","https://github.com/asaeed/RobotDrummer","http://blog.ianlee.info/2011/10/netmf-extension-methods.html"]},"media":[{"url":"https://niltoid.com/blog/netduino-robot-drummer/netduino.jpg","alt":""},{"url":"https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144935.jpg","alt":""},{"url":"https://niltoid.com/blog/netduino-robot-drummer/450px-solenoidarduinotip120.png","alt":""},{"url":"https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144715.jpg","alt":""},{"url":"https://niltoid.com/blog/netduino-robot-drummer/knock_bb.png","alt":""},{"url":"https://niltoid.com/blog/netduino-robot-drummer/img_20120824_144919.jpg","alt":""}]},{"slug":"arduino-wifly-sends-osc","title":"Arduino + WiFly sends OSC","date":"2012-07-10","summary":"Generating OSC messages directly on an Arduino and transmitting them over Wi-Fi, without an Ethernet shield or an intermediary computer.","url":"https://niltoid.com/blog/arduino-wifly-sends-osc/","tags":["tutorial","Arduino","WiFly","OSC","UDP","C++"],"skills":["protocol implementation","wireless networking"],"themes":["robots-hardware"],"dek":"","bodyText":"OSC is a widely used protocol for wireless communication between devices.  Arduino is a tremendously popular platform to create physical computing devices.  So naturally, one would think that engaging in OSC communication using Arduino’s would be straight-forward and well documented.  Unfortunately, I found very little help on the internet on this topic.  Most searches led to one of two existing methods to get OSC out of an Arduino:\n \n1.  Using Processing as a middleman – this requires sending data from the Arduino over serial to a computer running Processing, which then generates and transmits OSC.  So to talk between two Arduino’s, an entire computer is required?  No good.\n \n2.  Using the Ethernet Sheild and a library called ArdOSC – excellent stuff, but this library is written to work with the ethernet library only, and I’m using an RN-XV WiFly module.  No wires.\n \nNeither of these solutions worked for me so I figured this is a topic worth exploring further.  Previously, I had been able to use the RN-XV to send raw data over UDP.  OSC data is also transmitted over UDP, so it should just be a matter of correctly generating OSC on the Arduino.\n \nStart Simple\n \nTo test this hypothesis, I took some simple OSC from OpenSoundControl.org\n 2f (/)  6f (o)  73 (s)  63 (c)\n 69 (i)  6c (l)  6c (l)  61 (a)\n 74 (t)  6f (o)  72 (r)  2f (/)\n 34 (4)  2f (/)  66 (f)  72 (r)\n 65 (e)  71 (q)  75 (u)  65 (e)\n 6e (n)  63 (c)  79 (y)  0 ()\n 2c (,)  66 (f)  0 ()    0 ()\n 43 (C)  dc (Ü)  0 ()    0 ()\n\nThe byte array equivalent in C for Arduino looks like this:\n\nchar data[] = {0x2f, 0x6f, 0x73, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x34, 0x2f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x00, 0x2c, 0x66, 0x00, 0x00, 0x43, 0xdc, 0x00, 0x00};\n\nSince this is kind of difficult to look at and work with, we can instead use char arrays.  Char arrays can be more readable, but how do you convert a float to a char array?  There’s a neat “trick” to do this in C using the union keyword.  Here’s some working Arduino code for sending OSC messages with a single float argument.  The first message sends 0.1, the next 0.2, and so on until 1.0 is reached and then it’s reset back to 0.1.\n\n#include \"RNXV.h\"\n\nRNXV rnxv = RNXV();\nfloat f;\nunion u_tag {\n  byte b[4];\n  float fval;\n} u;\nvoid setup() {\n  f = 0.1;\n\n  Serial.begin(9600);\n  Serial1.begin(9600);\n\n  rnxv.setUart(&Serial1);\n  rnxv.join(\"SSID_HERE\",\"PASSPHRASE_HERE\");\n  rnxv.enableUdp(\"192.168.1.5\", 3000, 4000);\n  rnxv.sendCommand(\"join\", \"AOK\");\n  Serial.println(rnxv.ip());\n}\nvoid loop()\n{\n  delay(1000);\n  if (f > 1) f = 0;\n  f = f + 0.1;\n\n  char data[32] = \"/oscillator/4/frequency\\0,f\\0\\0\";\n  u.fval = f;\n  data[28] = u.b[3];\n  data[29] = u.b[2];\n  data[30] = u.b[1];\n  data[31] = u.b[0];\n\n  Serial.print(\"print use loop: \");\n  for (int i = 0; i <= 31; i++){\n    Serial.print(data[i]);\n  }\n  Serial.println();\n\n  rnxv.sendOsc(data, 32);\n}\n\nThe code references an RN-XV library I’ve been working on to set up UDP and send the byte array as follows:\n\nvoid RNXV::sendOsc(char data[], int size)\n{\n  for(int i = 0; i < size; i++)\n    _uart->print(data[i]);\n  delay(75);\n}\n\nI tried various delays and a delay of 75 seemed just enough that there wouldn’t be any corrupted OSC messages even when running the code for hours. This delay and the minimal code above resulted in about 13 OSC messages transmitting per second.  It is also necessary to loop and send the exact number of chars as a message contains, or else the receiving end doesn’t recognize the end of the message and throws errors.\n\n \nOn the receiving end, I once again used the sample app that comes with Cinder and it’s OSC Cinder block.  See the “Listening with Cinder” section in this post to see how to run the sample app, no code is required.  (Note that you may need to restart the app once because at first it inadvertently receives a message “exit” which is the RN-XV going into data mode).  If everything is working you should see a window like this one where the white section slowly expands:\n\n OscPkt and AVR-STL\n\nAt this point, having proved the concept, I was about to dive into writing my own library to generate the OSC, but thought I’d try one last time to find something off the shelf to do this.\n\nOscPkt, the minimalittlest OSC library for C++ seemed perfect for the job, being super concise and all contained in a single header file. It also was not tightly coupled with any UDP library so I could use my sendOsc function (above). However it depended heavily on C++ Standard Library classes (like vector) which don’t exist for Arduino.\n\nExcept they do – a brilliant piece of work by Andy Brown is AVR-STL. It brings STL to Arduino. He has all the instructions on his blog post.  Simply download and put all header files in the include folder into …arduino-1.0.1\\hardware\\tools\\avr\\avr\\include.  \n\nOnce AVR-STL was integrated, I took oscpkt.hh, renamed it to oscpkt.h and added the following two #includes at the top (as per the instructions found on the AVR-STL page):\n\n#include\n#include\n\nThen placed it in a folder “oscpkt” which I threw into my Arduino “libraries” folder. Now you can add the following to any Arduino sketch:\n\n#include \"oscpkt.h\"\nsetup() {\n  oscpkt::Message msg;\n  oscpkt::PacketWriter wr;\n  msg.init(\"/foo\");\n  wr.init().addMessage(msg);\n  Serial.println(wr.packetSize());\n  Serial.println(wr.packetData());\n}\n\n \n\nPrevious posts about this project include the following topics:\n \n1.  A low-cost and easy Robot Chassis to serve as the body of the robot.\n2.  Adding a RN-XV WiFly Module to enable wi-fi connectivity.\n3.  A Python Server which communicates with the robot.\n4.  Adding a Sensor and Actuator and transmitting data as JSON.\n \nIn #3 and #4, I utilized a Python Server with JSON as the data format.  Here we try out a C++/Cinder Server with OSC as the communication protocol.","projects":[{"name":"WiFiRobot","repo":"https://github.com/asaeed/WiFiRobot"}],"links":{"body":["https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_234251.jpg","https://github.com/recotana/ArdOSC","http://niltoid.blogspot.com/2012/02/rn-xv-wifly.html","http://niltoid.blogspot.com/2012/03/arduino-talks-to-python.html","http://opensoundcontrol.org/spec-1_0-examples#OSCstrings","https://github.com/asaeed/WiFiRobot/tree/master/RNXV","https://niltoid.com/blog/arduino-wifly-sends-osc/osctest.png","http://niltoid.blogspot.com/2012/05/ableton-live-talks-osc-to-cinder.html","http://gruntthepeon.free.fr/oscpkt/","http://andybrown.me.uk/wk/2011/01/15/the-standard-template-library-stl-for-avr-with-c-streams/","https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_234131.jpg","http://niltoid.blogspot.com/2012/01/magician-chassis-from-sparkfun-is-very.html","http://niltoid.blogspot.com/2012/04/robots-first-sensor-and-actuator.html","https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_233723.jpg"]},"media":[{"url":"https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_234251.jpg","alt":""},{"url":"https://niltoid.com/blog/arduino-wifly-sends-osc/osctest.png","alt":"Cinder OSC listener displaying a white signal bar"},{"url":"https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_234131.jpg","alt":"Arduino robot with a raised metal frame and WiFly module"},{"url":"https://niltoid.com/blog/arduino-wifly-sends-osc/img_20120708_233723.jpg","alt":"Robot prototype and electronics tools on the workbench"}]},{"slug":"cinder-box2d","title":"Cinder + Box2D","date":"2012-06-24","summary":"Integrating Box2D with Cinder, from a sample project to converting between the physics engine’s objects and rendered graphics.","url":"https://niltoid.com/blog/cinder-box2d/","tags":["tutorial","Cinder","Box2D","C++"],"skills":["physics simulation","real-time graphics"],"themes":["graphics-3d"],"dek":"","bodyText":"Box2D is a popular 2D physics engine for C++.  It’s free and open source and pretty easy to integrate with Cinder.  I recently tried out another engine called MSAPhysics and wrote a tutorial on setting it up with Cinder.  It’s a great little library, super easy to get up and running, and can even do a good job of 3D physics, however it lacks some advanced features and there’s very little community contributed code behind it.  So I thought I’d try out an alternative and see how they compare.  My friends at OneDayItWillMake and Wu-Media had spoken highly of Box2D and have used it in iOS games and with Cinder in Eclipse on OSX.  In this post, I attempt to integrate it with Cinder in VisualStudio 2010 on Windows 7.\n\nUsing b2cinder\n\nFirst, I tried out a sorta Cinder block in progress called b2cinder by David Wicks (aka sansumbrella).  His sample project already takes care of some of the code needed to convert Box2D objects to Cinder objects and vice versa.  No coding needed for this part…\n\n1.  Download this repo https://github.com/sansumbrella/sc-Box2D\n \n2.  Place sc-Box2D in cinder/blocks folder\n \n3.  Open BasicBox2D sample app in vc10 folder\n \n4.  Make sure these properties have correct paths:\n    C/C++ –> General –> Additional Include Directories\n    Linker –> General –> Additional Library Directories\n \n5.  Had to add “using namespace ci;” to the following code files:\n    Sandbox.cpp\n    BoxElement.cpp\n    BoundaryElement.cpp\n    \n6.  In Solution right-click Header Files and Add Existing…\n    Add all files and sub-directories within sc-Box2D/include/b2Cinder and sc-Box2D/include/Box2D.\n \nNow you should be able to run the app and this is what it looks like.\n\nIntegrating Box2D From Scratch\n \nNext I wanted to try out the latest and greatest version of Box2D, since sansumbrella’s version was slightly older.  \n \n\n1. Create BasicApp in TinderBox called Box2DTest\n \n2. Download Box2D from  http://code.google.com/p/box2d/ \n \n3. Open vc10 .sln file and build Box2D project.\n \n4. Copy Box2D.lib file created into new folder in Box2DTest called “lib”\n5. In Linker –> General –> Additional Library Directories\n\n    add path to “lib” folder you just created\n \n    In C/C++ –> General –> Additional Include Directories \n    add path to Box2D_v2.2.1\n \n    Note: be sure to add these to both Debug and Release run configs\n\n6. Add this to top of code file:\n    #include <Box2D/Box2d.h>\n \n7. Under “Header Files”, add all .h and .cpp files to Solution.\n \n8. Create a Box2D World with gravity.\n    b2Vec2 gravity(0.0f, 10.0f);\n    b2World world(gravity);\n \n9. Add the file Conversions.h from b2cinder lib which does pretty good job of converting between box2d and cinder floats, vec2f, and more.\n \n10. Code\n \nHere is the source code on GitHub for a quick example I created using these steps:\nhttp://github.com/asaeed/Box2DTest\n \nAnother screenshot:","projects":[{"name":"Box2DTest","repo":"https://github.com/asaeed/Box2DTest"}],"links":{"body":["https://niltoid.com/blog/cinder-box2d/box2d.png","http://box2d.org/","http://niltoid.blogspot.com/2012/06/cinder-msaphysics.html","http://onedayitwillmake.com/blog/","http://wu-media.com/","http://sansumbrella.com/","https://github.com/sansumbrella/sc-Box2D","https://niltoid.com/blog/cinder-box2d/box2d_orig.png","http://code.google.com/p/box2d/","https://github.com/asaeed/Box2DTest","https://niltoid.com/blog/cinder-box2d/box2dpurple.png"]},"media":[{"url":"https://niltoid.com/blog/cinder-box2d/box2d.png","alt":""},{"url":"https://niltoid.com/blog/cinder-box2d/box2d_orig.png","alt":"Box2D simulation with a pile of orange and yellow squares"},{"url":"https://niltoid.com/blog/cinder-box2d/box2dpurple.png","alt":"Box2D simulation with purple squares falling into a pile"}]},{"slug":"cinder-msaphysics","title":"Cinder + MSAPhysics","date":"2012-06-07","summary":"Getting MSAPhysics samples running with Cinder in Visual Studio, then adding the physics library to a new project.","url":"https://niltoid.com/blog/cinder-msaphysics/","tags":["tutorial","Cinder","MSAPhysics","C++"],"skills":["physics simulation","real-time graphics"],"themes":["graphics-3d"],"dek":"","bodyText":"MSAPhysics is a simple and light-weight physics engine for Cinder or OpenFrameworks created by Memo Aktens.  I downloaded it from his git repository where he hosts a bunch of useful C++ libraries and decided to try it in conjunction with Cinder in VisualStudio 2010.  Unfortunately the VS2010 sample apps that came with it, didn’t work right away.  The MSAPhysics lib hasn’t been kept up to date in a couple of years.  For this reason many prefer to go with Box2D for a better supported, fully featured, and robust physics engine.  MSAPhysics is a great alternative if you want to do something really quick in a 2D or 3D world.  Here are the simple steps for first getting MSAPhysics samples working and then to add the MSAPhysics library to a new project.  This requires setting up Cinder as described here, as well as VisualStudio 2010.\n\nGet msaPhysicsBasic Cinder Sample App Working\n\nThe sample app is very useful for learning how to use MSAPhysics and see it’s potential.\n\n1. Open the vc10 solution msaPhysicsBasic\n\n2. Fix the following properties.  Adjust the paths to point to your cinder directories…\n    C/C++ –> General –> Additional Include Directories\n    Linker –> General –> Additional Library Directories (added extra ../ in my case)\n \n3. Copy all the .h and .cpp files found in the following mslibs src folders\n    MSAPhysics\n    MSACore\n    MSAObjCPointer\n \n    Paste into the sample projects include folder\n \n4. Now right-click Sln –> Header Files and add all the files you just copied.  Looks like this now:\n\n5. In MSACore.h, uncomment this line: #define MSA_HOST_CINDER\n \n6. Make sure both of the following are included in your main app:\n\n    #include “MSAPhysics.h”\n    #include “MSAPhysics3D.h”\n\n \n7. Make following replacements in the main app:\n\n    Physics::World3D physics;\n    Physics::Particle3D mouseNode;\n    //Physics::World physics;\n    //Physics::Particle mouseNode;\n\n \n    Also change all occurrences of Particle, Spring, and more to Particle3D, Spring3D, etc\n \n9. Change anywhere you have something like \n    a->getX() \n    to\n    a->getPosition().x\n    \n10. Change loadResource() call to loadAsset() and put ball.png into a folder called “assets” in sample app folder\n \n\n \nGet MSAPhysics into a new Cinder App\n \n\n1. Create Basic App in TinderBox (which comes with the windows distribution of Cinder 0.84)\n \n\n2. Copy all the .h and .cpp files found in the following mslibs src folders\n    MSAPhysics\n    MSACore\n    MSAObjCPointer\n \n    Paste into the sample projects include folder\n\n3. Add the files you just copied under Sln -> Header Files (see screenshot above).\n\n4. In MSACore.h, uncomment this line:  #define MSA_HOST_CINDER\n \n5. Add this line to the top of your main cpp file:  #include “MSAPhysics2D.h”\n    Optionally add this line:  using namespace MSA;\n \n6. Code\n \nA Quick Test App I Created\n \nHere is some source code from my own experiments with MSAPhysics.  I wanted to be able to abstract out a particle system that uses MSAPhysics.  I define the Physics::World2D in the main app.  Then, when initializing the ParticleController, I pass in a reference to World2D.  Then when creating each Particle, the ParticleController also creates a Physics::Particle2D, and passes it’s reference to its corresponding Particle instance to store.  This way a Particle can draw itself using data from the physics world, as well as it’s own member data such as a color.\n \nHere is the end result","projects":[{"name":"MSAPhysicsTest","repo":"https://github.com/asaeed/MSAPhysicsTest"}],"links":{"video":"https://www.youtube.com/watch?v=IMv9KjuKUro","body":["https://niltoid.com/blog/cinder-msaphysics/msaphysicstest.png","http://www.memo.tv/msaphysics/","http://www.memo.tv/","https://github.com/memo/msalibs","http://libcinder.org/docs/welcome/GitSetup.html","https://niltoid.com/blog/cinder-msaphysics/msaphysicstest_headers.jpg","https://niltoid.com/blog/cinder-msaphysics/msaphysicstest2.png","https://github.com/asaeed/MSAPhysicsTest"]},"media":[{"url":"https://niltoid.com/blog/cinder-msaphysics/msaphysicstest.png","alt":""},{"url":"https://niltoid.com/blog/cinder-msaphysics/msaphysicstest_headers.jpg","alt":"Visual Studio project tree showing the MSAPhysics header files"},{"url":"https://niltoid.com/blog/cinder-msaphysics/msaphysicstest2.png","alt":"MSAPhysics particle simulation with orange circles"}]},{"slug":"ableton-live-talks-osc-to-cinder","title":"Ableton Live Talks OSC to Cinder","date":"2012-05-15","summary":"Sending track levels, beats and control changes from Ableton Live to a Cinder application over OSC to drive interactive visuals.","url":"https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/","tags":["tutorial","Ableton Live","LiveOSC","OSC","Cinder","C++"],"skills":["real-time graphics","audio-reactive visuals"],"themes":["sound-visuals"],"dek":"","bodyText":"The goal here is to have Ableton Live transmit all track data and user actions to a C++ program which can use that data to generate unique visuals.  If you want to create interactive visuals for a music performer, the obvious way is to use a live audio feed.  However you can only do so much with such a feed and visuals end up only responding to the master level.  With the help of a tool called LiveOSC, it’s possible to get OSC data out of Ableton Live.  OSC or Open Sound Control is a data format which is usually transmitted over a wifi using a protocol called UDP, and this data can be picked up by a C++ application.  In this case we’re using a C++ framework called Cinder and the OSC is interpreted into visualizations.  This OSC data can tell us stuff like:\n\n– when the set begins or ends\n– when each beat occurs (as in once a second for 60 bpm)\n– when any track level or the master level is changed\n– when the user switches to the next track\n– when the user tweaks any knob\n\nI’m using the following tools to accomplish this task.\n\n– Ableton Live 8.2.6 (OSX in my case)\n– LiveOSC\n– Cinder\n– XCode or VisualStudio 2010 (or Eclipse which I’m using, but that’s a whole other topic)\n\nAbleton Live gets LiveOSC\n\nLiveOSC is a simple way to get OSC data out of Live.  It’s hosted here by its creator:\nThere’s not much help on the site, but it really is that simple to get it working.\n\n1. install python 2.5.1 (Do not skip!)\n2. place LiveOSC in Live.App/Contents/App-Resources/MIDI Remote Scripts/\n3. go to Preferences -> MIDI Sync and select LiveOSC as a Control Surface\n\nLive should now be transmitting OSC data over UDP on port 9001, as well as listening on port 9000.  However we don’t yet have a way of listening to the transmission.  You could probably use some sort of network monitoring tool to check if it’s working.  But it’s actually easier to proceed with setting up the next tool, Cinder, since it comes with a sample app called OSCListener which will pick up this OSC data and parse and display it.\n\n[As an aside, by default LiveOSC seems to transmit to it’s own host machine’s IP, my next goal is to make it transmit to a different IP]\n\nListening with Cinder\n\nCinder is an excellent C++ framework that makes it a breeze to make complex interactive and visual apps. You can download it for free and it comes with many sample apps as well as a set of tutorials by a talented artist, Robert Hodgin.  My preferred way of setting up Cinder is with Git, using these instructions.\nOnce you are setup correctly, you should be able to launch any of the sample apps that the Cinder library comes with.  Go into cinder/blocks/osc/samples/OscListener/ and then launch either the Xcode or VS2010 app depending on your platform of choice.\n\nNow in the source file OscListenerApp.cpp, make one simple change.  Look for the following line and change the port number from 3000 to 9001:\n\nlistener.setup(9001);\n\nNow run OscListenerApp and then go to Ableton Live and move the master level slider up and down.  You should see some OSC data pop up in you Xcode console!\n\nThe master level slider will also effect the OscListener app screen.  The white part of the window should extend to the right as you increase the volume.  This slider will have this effect while others may not.  In the code the simple visual effect is only performed when the first argument is a float.\n\nMaking sense of the OSC\n\nI’m still figuring out the nitty gritty of interpreting the OSC messages from LiveOSC.  Most of it is pretty self explanatory.  Here’s an example.  The output is reformatted so it looks more readable (to me)\n \n\n–> /live/play  #args:1  [0]int32: 2  \n–> /live/beat  #args:1  [0]int32: 1  \n–> /live/beat  #args:1  [0]int32: 2  \n–> /live/beat  #args:1  [0]int32: 3  \n–> /live/beat  #args:1  [0]int32: 4  \n–> /live/beat  #args:1  [0]int32: 5  \n–> /live/beat  #args:1  [0]int32: 6  \n–> /live/scene  #args:1  [0]int32: 3  \n–> /live/clip/info  #args:3  [0]int32: 0  [1]int32: 2  [2]int32: 3  \n–> /live/beat  #args:1  [0]int32: 7  \n–> /live/clip/info  #args:3  [0]int32: 0  [1]int32: 1  [2]int32: 1  \n–> /live/clip/info  #args:3  [0]int32: 0  [1]int32: 2  [2]int32: 2  \n–> /live/beat  #args:1  [0]int32: 8  \n–> /live/beat  #args:1  [0]int32: 9  \n–> /live/beat  #args:1  [0]int32: 10  \n–> /live/beat  #args:1  [0]int32: 11  \n–> /live/play  #args:1  [0]int32: 1\n\nThings to note:\n– we get a message on start and stop with the address /live/play\n– we get a message on every beat with the address /live/beat\n– we get a message when switching tracks with the address /live/clip/info\n– the last argument in some cases is an int that represents the following values:\n\n0 = empty\n1 = stopped\n2 = playing\n3 = triggered\n\nSo the 3 /live/clip/info messages were sent when I triggered the new clip, the old clip stopped, and the new clip started.\n\nTouchOSC talks to Cinder\n\nThis section is not really related to the above, but is another simple proof of concept.  Another way to send OSC signals to a Cinder app is to use your phone.  Just install an app called TouchOSC (free on Android, $5 and more full featured on iOS).  Make sure your phone and computer are connected to the same wifi network, open up TouchOSC, and configure it with the following settings:\n\nHost: 192.168.1.2             Port (outgoing):  9001\nPort (incoming):  9000\n\nNow just start up one of the touch layouts in TouchOSC, start up your OscListener app, and like magic, you should see messages coming in to your Cinder app.","projects":[],"links":{"body":["https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-13-at-11.30.48-pm.png","http://www.ableton.com/live","http://livecontrol.q3f.org/ableton-liveapi/liveosc/","http://opensoundcontrol.org/","http://libcinder.org/","https://developer.apple.com/xcode/","http://www.microsoft.com/visualstudio","http://eclipse.org/","https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-14-at-11.26.11-pm.png","http://libcinder.org/docs/v0.8.3/hello_cinder.html","http://www.flight404.com/blog/","http://libcinder.org/docs/welcome/GitSetup.html","https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-14-at-11.37.58-pm.png","http://hexler.net/software/touchosc","https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/touchosc-screens-01.png"]},"media":[{"url":"https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-13-at-11.30.48-pm.png","alt":""},{"url":"https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-14-at-11.26.11-pm.png","alt":"Ableton Live preferences with LiveOSC selected as a control surface"},{"url":"https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/screen-shot-2012-05-14-at-11.37.58-pm.png","alt":"Xcode console displaying OSC messages received from Ableton Live"},{"url":"https://niltoid.com/blog/ableton-live-talks-osc-to-cinder/touchosc-screens-01.png","alt":"TouchOSC control layouts on a tablet and phone"}]},{"slug":"wifi-bike-lock","title":"WiFi Bike Lock","date":"2012-05-07","summary":"A hackathon prototype for an electronic bicycle lock controlled from an iOS app, using an Arduino, a WiFly module and a servo.","url":"https://niltoid.com/blog/wifi-bike-lock/","tags":["Arduino","WiFly","iOS","servo"],"skills":["prototyping","motor control"],"themes":["robots-hardware"],"dek":"","bodyText":"Took part in a Yahoo! and WPP sponsored hackathon this weekend and in 24 hours we whipped up this prototype for an electronic bike lock that can be controlled from an iOS app.  The lock consists of an Arduino, an RN-XV WiFly, and a servo.","projects":[],"links":{"body":["https://niltoid.com/blog/wifi-bike-lock/img_20120507_145104.jpg"]},"media":[{"url":"https://niltoid.com/blog/wifi-bike-lock/img_20120507_145104.jpg","alt":""}]},{"slug":"robots-first-sensor-and-actuator","title":"Robot’s First Sensor and Actuator","date":"2012-04-11","summary":"Adding a servo-driven head and a magnetometer to a Wi-Fi-connected robot, with metal construction-kit parts forming its torso.","url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/","tags":["tutorial","Arduino","robotics","servo","magnetometer"],"skills":["sensor integration","motor control"],"themes":["robots-hardware"],"dek":"","bodyText":"This is the fourth post in a pseudo-series about an autonomous wi-fi connected robot I’m working on. So far we’ve looked at:\n \n1.  A low-cost and easy Robot Chassis to serve as the body of the robot.\n2.  Adding a RN-XV WiFly Module to enable wi-fi connectivity.\n3.  A Python Server which communicates with the robot.\n \nTo reiterate, the idea is to have an Arduino robot which transmits sensor data over wi-fi to a Python server. The server then interprets the data and sends actuator commands back to the robot. We’ve achieved a round trip of data so far, next we try to refine what we have and add an actual sensor and actuator.\n \nRobot Torso and Head\n\nMy impulse buy a few weeks ago has actually come in handy to build up the body of the robot… The Eitech Classic Construction Kit includes all the flat metal pieces with holes which you see in the images above and below.\n \n\nAs these pictures show, I used the Eitech parts to make a simple rectangular frame for the torso. The Eitech screws are unfortunately a tiny bit too wide to screw into the acrylic top of the Magician Chassis, but some slightly smaller 4-40 size screws did the job. \n\nNeck Servo\n\nTechnically, the first actuators I added were the 2 wheel motors. However, I’m leaving them unplugged from their power source for now. Time to add a rotating head.  On top of this frame, I mounted an upside-down servo to serve as a head. Luckily the face plate easily attached to the servo using a couple of Eitech screws and nuts.\n\nClose-up of how servo is mounted \n\nA Sense of Direction \n\nNext I added an HMC5883L Magnetometer to serve as the robots first sensor. A magnetometer is just a simple digital compass. Its fairly straightforward to use and there’s a very good tutorial on Bildr which covers how to set it up with an Arduino. I plopped it onto the robot’s breadboard, hooked up the 4 wires required, tried the sample code from Bildr, and started getting data from it.\n\nOne thing to note however is that it’s not incredibly accurate. Especially if it’s placed physically next to a magnet (like a motor) or just a hunk of metal (like a breadboard)… Simply bringing my wire cutter near it would throw it off by 10-20 degrees or more. In addition, its lacking something called tilt compensation. Unfortunately compasses that include tilt compensation are about 10x the price. So you have to either (a) fork up the cash, (b) live with some error or (c) figure out ways to minimize the error in code or by re-positioning the module.  I’ll try to achieve (c) and hopefully revisit this in a later post.\n\nA Common Language\n\nNow that I had at least 1 sensor (the compass) and 1 actuator (the neck servo), there was finally some real data to communicate between the Arduino Robot and the Python Robot Base.  It was time to establish a common language for client and server.\n\nIn an earlier post, I set up communication between the 2 endpoints using UDP.  By the end, I had a simple string of text being transmitted back and forth:\n\n\"here is a longer string of data being sent back and forth\"\n\nNot very useful until you actually include some data.  In the past I’ve used simple comma delimited strings such as:\n\n\"12,34,56,78,90\"\n\nThis works fine if both endpoints knows what all these numbers mean.  For instance the arduino and the server both may know that the first number is the compass value (12), the second number is the proximity sensor value (34).  Works but is not very readable for humans.\n\nA better option is to use JSON, which is a concise, readable, standardized, and widely accepted data format.  Now I’m transmitting the following JSON string from the Arduino:\n\n{'ip':'192.168.1.6','heading':144}\n\nFirst you may note that I’m sending the IP address of the robot. This is in case messages are being sent from multiple robots or devices, the Python server will know who to respond to with what commands. I created a funtion in my RNXV library called ip() to do this.  You can take a closer look at that library to see how the IP is retrieved.  Second, how do we actually create this JSON string?  One option is to construct the string manually. A better way is to use a tremendously helpful library called aJSON.  Check out the source code to see how it’s used.\n\nOn the Python side, once the string is received, we parse it and interpret the data.  For the parsing, it just so happens that the JSON format very closely resembles the code to create a dictionary in Python.  This is how you’d create a dictionary in Python:\n\ndata = { 'ip': '192.168.1.6', 'heading': 144 }\n\nSo we can simply take the JSON string and use the eval function to build a dictionary.\n\ndataRaw, addr = sock.recvfrom( 1024 )\ndata = eval(dataRaw)\n\nThis is a temporary measure.  It may break down when we have more complex JSON but is sufficient for now.  Later I would probably try to use a JSON library for Python.\n\nNow the Python server constructs a response JSON string to send back to the robot.  For starters we aren’t going to try to make any meaningful interpretations. The input value (compass heading) ranges from 0-359 and the output value (neck servo position) ranges from 0-179.  So a simple divide by 2 will give us some result to observe.\n\ns = '{\"neck\":' + str(heading / 2) + \"}\"\n\nNow as you turn the robot in place 360 degree’s, you can observe the head turn 180 degrees. \n\nAs an aside, I experienced something very strange when I unplugged the USB cable from the robot and attempted to power it from an external battery.  The Arduino would crash almost instantly and stop sending messages to the server.  After some research, I discovered that this could be because of message fragments left on the serial buffer which it was trying to process but failing at.  I’m still not sure why it only occurs when using external power.  I did manage to find a very simple fix.  To make sure the JSON message was complete, I added a simple check to make sure the first character is a ‘{‘ and the last is a ‘}’.\n\nErrors would occasionally also occur on the Python side because of badly formatted JSON.  So I added the same check in the Python code and that reduced crashes substantially.  Once in a while there is still a crash because somehow an odd byte gets lost in the transmission in either direction.  Eventually, I will add some more JSON validation to avoid such crashes. At this point, however, I’m still able to keep the robot running for hours with no problems.\n\nHere is the python RobotServer code:\n\nimport socket\nimport time\nimport math\n\nUDP_IP=\"192.168.1.7\"\nUDP_PORT=3000\n\nsock = socket.socket( socket.AF_INET, # Internet\n                      socket.SOCK_DGRAM ) # UDP\nsock.bind( (UDP_IP,UDP_PORT) )\n\nwhile True:\n    dataRaw, addr = sock.recvfrom( 1024 )\n    #prints a string but crashes on OSC msg\n    #print(\"received: \" + data.decode(“utf-8″))\n\n    if dataRaw[0] == 123 and dataRaw[-1] == 125: #check for '{' and '}'\n        data = eval(dataRaw)\n        ip = data[\"ip\"]\n        heading = data[\"heading\"]\n        s = '{\"neck\":' + str(heading / 2) + \"}\"\n        print(dataRaw + b\"  —->  ” + bytes(s,\"utf-8\"))\n        if len(dataRaw) > 0:\n            sock.sendto( bytes(s,\"utf-8\") + b\"\\n\", 0, (ip, 4000) )\n\nHere is the repo containing the WiFiRobot’s Arduino code.","projects":[{"name":"WiFiRobot","repo":"https://github.com/asaeed/WiFiRobot"}],"links":{"body":["https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_165840.jpg","https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_170429.jpg","http://niltoid.blogspot.com/2012/01/magician-chassis-from-sparkfun-is-very.html","http://niltoid.blogspot.com/2012/02/rn-xv-wifly.html","http://niltoid.blogspot.com/2012/03/arduino-talks-to-python.html","http://niltoid.blogspot.com/2012/02/impulse-buy-of-week.html","http://eitechamerica.com/Classics/C05/Eitech_C05.html","https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120323_031739.jpg","https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_180145.jpg","http://www.sparkfun.com/products/10530","http://bildr.org/2012/02/hmc5883l_arduino/","http://dlnmh9ip6v2uc.cloudfront.net/images/products/10530-01c.jpg","http://lmgtfy.com/?q=JSON","http://interactive-matter.eu/2010/08/ajson-handle-json-with-arduino/","https://github.com/asaeed/WiFiRobot"]},"media":[{"url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_165840.jpg","alt":""},{"url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_170429.jpg","alt":"Robot prototype with a tall metal frame above the chassis"},{"url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120323_031739.jpg","alt":"Robot prototype and construction parts on the workbench"},{"url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/img_20120325_180145.jpg","alt":"Close-up of the robot electronics and metal sensor mount"},{"url":"https://niltoid.com/blog/robots-first-sensor-and-actuator/10530-01c.jpg","alt":""}]},{"slug":"arduino-talks-to-python","title":"Arduino talks to Python","date":"2012-03-11","summary":"Replacing slow HTTP polling with UDP communication between an Arduino and a Python server, using an RN-XV WiFly module.","url":"https://niltoid.com/blog/arduino-talks-to-python/","tags":["tutorial","Arduino","Python","WiFly","UDP"],"skills":["wireless networking","socket programming"],"themes":["robots-hardware"],"dek":"","bodyText":"I’m in the process of creating a “Robot Command Center” in my home.  Basically my goal is to have Arduino devices sending sensor data to a central server and receiving commands from this server on what to do next. \n\nMy previous post described how to use a wi-fi chip called the RN-XV to get an arduino talk to a PHP web site. The problem with this HTTP over TCP based method was that all the connecting and disconnecting was slowing everything down.  The best it could do was just one exchange of data per second.  Luckily the RN-XV Wifly module has a UDP mode which seems better suited for fast communication.  UDP (an alternative to TCP) forgoes the formalities of handshaking and just starts yelling data over a port.\n\nThe following 4 commands are needed in the Arduino sketch to configure UDP on your RN-XV.  These commands enable UDP mode, set the ip of the host computer, and set the sending and receiving ports.  You’ll find them used in my Arduino code later in this post.\n\n  set ip proto 1\n   set ip host 192.168.1.XXX\n   set ip remote 3000\n   set ip local 4000\n\nNow the question of what to use for the central server.  My first attempt was to use C++ and Cinder which I’ve been exploring lately.  Cinder can easily communicate using OSC (Open Sound Control) data over a UDP connection.  However I had some trouble generating the OSC messages on the Arduino. I’m shelving this Arduino + WiFly + OSC + Cinder project for another day.\n\nMy next attempt was to use Python, which has great built-in networking functionality. First, tried installing Python on Windows 7, but after some early hurdles and research it seemed clear that it would be easier to run Python on an Ubuntu instance using VirtualBox.\n\nPsychocats has some great instructions for setting up VirtualBox + Ubuntu.\n\n1.  Download Ubuntu\n2.  Get VirtualBox + Ubuntu\n3.  Install Ubuntu\n4.  Select Bridged mode in VirtualBox settings \n\nAnd there you have it, a clean new Linux build with it’s own IP Address.\n\n \nNext I created a Shared Folder so I can edit the code on the host computer and have it copy right over to the Ubuntu instance.\n\n1.  Go to Devices->Install Guest Additions – this is required first\n 2.  Go to Devices->Shared Folders – make a shared folder\n 3.  Ctrl-Alt-T to open Terminal\n 4.  Type sudo mount -t vboxsf SHARE_FOLDER ~/Share\n(here substitute “SHARE_FOLDER” for what you created in step 2 and “~/Share” for whatever location you want that share to exist in Ubuntu)\n\nBack on the host machine, I made a quick python script called test.py containing 1 line of code:\n\nprint \"hi\"\n\nand placed it in the shared folder.  Now you can run it by going back to Ubuntu Terminal, navigating to where test.py lives, and typing \n\npython test.py\n\nYou should see “hi” show up as the output.\n\nNow use the following code on the Arduino (once you have hooked up the RN-XV as I’ve described in this post)\n\n#include \"RNXV.h\"\n\nint loopCount;\nRNXV rnxv = RNXV();\n\nvoid setup() {\n\n  Serial.begin(9600);\n  Serial1.begin(9600);\n  Serial.println(\"setup begin\");\n\n  rnxv.setUart(&Serial1);\n  Serial.println(\"uart set\");\n\n  rnxv.connect(\"your_ssid\",\"your_passphrase\");\n\n  rnxv.sendCommand(\"set ip proto 1\", \"AOK\");\n  rnxv.sendCommand(\"set ip host 192.168.1.7\", \"AOK\");\n  rnxv.sendCommand(\"set ip remote 3000\", \"AOK\");\n  rnxv.sendCommand(\"set ip local 4000\", \"AOK\");\n  rnxv.sendCommand(\"save\", \"AOK\");\n  rnxv.sendCommand(\"reboot\", \"READY\");\n\n  rnxv.sendCommand(\"join\", \"AOK\");\n\n  loopCount = 0;\n  Serial.println(\"setup end\");\n}\n\nvoid loop()\n{\n  sendData();\n  receiveData();\n}\n\nvoid sendData()\n{\n  loopCount++;\n  Serial1.print(loopCount);\n  Serial1.print(“here is a string of data being sent back and forth”);\n  delay(200);\n}\n\nvoid receiveData()\n{\n  while (Serial1.available() > 0) {\n    Serial.write(Serial1.read());\n  }\n}\n\nI whipped up a simple library to work with the RN-XV.\nHere is the header file RNXV.h:\n\n#ifndef RNXV_h\n#define RNXV_h\n\n#include \"Arduino.h\"\n\nclass RNXV\n{\npublic:\n  RNXV();\n  void setUart(Stream* uart);\n  void print(char* str);\n  void println(char* str);\n  void enterCommandMode();\n  void exitCommandMode();\n  void sendCommand(char* cmd, char* response);\n  bool connect(char* ssid, char* phrase);\n  bool awaitResponse(const char* toMatch, unsigned int timeOut);\n  bool awaitResponse(const char* toMatch);\n\nprivate:\n  Stream* _uart;\n};\n#endif\n\nAnd here is the corresponding RNXV.cpp.  Remember that both these files go in a folder called “RNXV” which is placed in your Arduino libraries directory.\n\n#include \"Arduino.h\"\n#include \"RNXV.h\"\n\nRNXV::RNXV()\n{\n}\n\nvoid RNXV::setUart(Stream* uart)\n{\n  _uart = uart;\n\n  enterCommandMode();\n  println(\"set comm idle 0\");\n  awaitResponse(\"AOK\");\n  println(\"set ip proto 2\");\n  awaitResponse(\"AOK\");\n}\n\nvoid RNXV::print(char* str)\n{\n  _uart->print(str);\n  delay(250);\n}\n\nvoid RNXV::println(char* str)\n{\n  _uart->print(str);\n  _uart->print(\"\\r\");\n  delay(250);\n}\n\nvoid RNXV::enterCommandMode()\n{\n  print(\"$$$\");\n  awaitResponse(\"CMD\");\n}\n\nvoid RNXV::exitCommandMode()\n{\n  print(\"exit\\r\");\n  awaitResponse(\"EXIT\");\n}\n\nvoid RNXV::sendCommand(char* cmd, char* response)\n{\n  enterCommandMode();\n  print(cmd);\n  print(\"\\r\");\n  awaitResponse(response);\n  exitCommandMode();\n}\n\nbool RNXV::connect(char* ssid, char* phrase)\n{\n  enterCommandMode();\n  print(\"set wlan phrase \"); println(phrase);\n  awaitResponse(\"AOK\");\n\n  print(\"set wlan ssid \"); println(ssid);\n  awaitResponse(\"AOK\");\n\n  println(\"save\");\n  awaitResponse(\"AOK\");\n\n  println(\"reboot\");\n  awaitResponse(\"READY\");\n\n  delay(2000);\n  println(\"join\");\n  awaitResponse(\"Associated!\");\n\n  exitCommandMode();\n  return true;\n}\n\nbool RNXV::awaitResponse(const char* toMatch){\n  awaitResponse(toMatch, 1000);\n}\n\nbool RNXV::awaitResponse(const char* toMatch, unsigned int timeOut = 1000) {\n  int byteRead;\n  unsigned long timeOutTarget;\n\n  for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {\n    timeOutTarget = millis() + timeOut;\n\n    while (!_uart->available()) {\n      if (timeOut > 0) {\n        if (millis() > timeOutTarget) {\n          return false;\n        }\n      }\n      delay(1);\n    }\n\n    byteRead = _uart->read();\n    delay(10);\n    if (byteRead != toMatch[offset]) {\n      offset = 0;\n      if (byteRead != toMatch[offset]) {\n        offset = -1;\n      }\n      continue;\n    }\n  }\n\n  return true;\n}\n\nAnd use the following basic Python code on Ubuntu\n\nimport socket\nimport time\n\nUDP_IP=\"192.168.1.7\"\nUDP_PORT=3000\n\nsock = socket.socket( socket.AF_INET, # Internet\n                      socket.SOCK_DGRAM ) # UDP\nsock.bind( (UDP_IP,UDP_PORT) )\n\nwhile True:\n    data, addr = sock.recvfrom( 1024 )\n    print \"received message:\", data\n    if len(data) > 0:\n        sock.sendto( data + \"\\n\", 0, ('192.168.1.5', 4000) )\n        time.sleep( .2 )\n\nAs you may have guessed, in my case 192.168.1.7 is the IP of the Ubuntu instance (which listens on port 3000) and 192.168.1.5 is the IP of the Arduino’s WiFly module (which listens on port 4000).  Replace these to suit your local network.  \n\nI’m sure my code could use numerous improvements but this is a good start to having your Arduino device talk to a Python server over your wi-fi network.  Here is the output you should see on your Arduino serial terminal:\n\nAnd here is the corresponding output that the Python program produces:\n\nAs an aside, try downloading an app called TouchOSC on your Android or iOS phone or tablet.  Since OSC is transmitted over UDP as well, you can easily configure TouchOSC to point to your Ubuntu’s IP and listening port, and you get instant communication!","projects":[],"links":{"body":["http://niltoid.blogspot.com/2012/02/rn-xv-wifly.html","http://en.wikipedia.org/wiki/User_Datagram_Protocol","http://libcinder.org/","http://www.psychocats.net/ubuntu/getting","http://www.psychocats.net/ubuntu/virtualbox","http://www.psychocats.net/ubuntu/installing","https://niltoid.com/blog/arduino-talks-to-python/ubuntu.jpg","https://niltoid.com/blog/arduino-talks-to-python/arduinoudp.jpg","https://niltoid.com/blog/arduino-talks-to-python/pythonudp.jpg","https://niltoid.com/blog/arduino-talks-to-python/pythonosc.jpg"]},"media":[{"url":"https://niltoid.com/blog/arduino-talks-to-python/ubuntu.jpg","alt":""},{"url":"https://niltoid.com/blog/arduino-talks-to-python/arduinoudp.jpg","alt":"Arduino serial monitor displaying incoming UDP messages"},{"url":"https://niltoid.com/blog/arduino-talks-to-python/pythonudp.jpg","alt":"Python terminal displaying UDP messages received from Arduino"},{"url":"https://niltoid.com/blog/arduino-talks-to-python/pythonosc.jpg","alt":"Python terminal displaying OSC messages from TouchOSC"}]},{"slug":"rn-xv-wifly","title":"RN-XV WiFly","date":"2012-02-23","summary":"Connecting an Arduino robot to Wi-Fi with an RN-XV module, including wiring, HTTP polling and the module’s ad-hoc configuration mode.","url":"https://niltoid.com/blog/rn-xv-wifly/","tags":["tutorial","Arduino","WiFly","Wi-Fi","robotics"],"skills":["wireless networking","serial communication"],"themes":["robots-hardware"],"dek":"","bodyText":"The RN-XV WiFly Module from Roving Networks is an affordable way to go wireless with your Arduino project.  It’s $35 and you only need 1 to get started, assuming you have a wi-fi adapter in your computer as well.  Previously, only the more expensive options such as the WiFly GSX ($85) were available.  I’m not sure, but I assume the price difference is mainly due to signal strength differences.  There are currently more resources and Arduino libraries available online for the WiFly GSX or WiFly Sheild, since they’ve been around longer.  However, the RN-XV is gaining popularity fast and I hope to see future versions of these WiFly libraries work more reliably for the RN-XV.\n \nIf you don’t care about connecting to a wi-fi network, and instead want simple point to point wireless serial communication, another alternative is the hugely popular Xbee Module.  However you do need a couple of them to set up 2 endpoints and get started, as well as a couple of breakout boards (an XBee Explorer Regulated and an XBee Explorer USB or Dongle).  So the cost adds up quickly and you end up paying close to $80 total.  XBee’s are totally worth the higher price point though.  i found them to be much more easy to work with than WiFly Modules and there’s an endless amount of documentation and examples of their use on the web.\n \nBut back to the RN-XV.  It was made to be easily swapped with an XBee so it has the exact same footprint.  This means it’s pins have a 2mm pitch, so you need a breakout board to hook it up to a breadboard or regular PCB which have slightly wider pin holes.  For this purpose, be sure to use a plain old XBee Breakout Board ($3).  DO NOT use the XBee Explorer Regulated!  I spent hours banging my head against a wall when I originally hooked it up to a Regulated I had lying around.  The circuitry on the XBee Explorer Regulated prevents the RN-XV from properly working.  They are NOT compatible.  \n \nI started out by attaching a bread board to my Robot Chassis.  Since I didn’t want to permanently attach the breadboard using the adhesive tape, I instead stuck it to a piece of cardboard and then used little screws and nuts to attach the cardboard to the acrylic.  Then plug the RN-XV into the XBee Breakout Board and the whole thing into the bread board.  Then make the following 4 connections between the Arduino (Mega in my case) and the RN-XV.\n \nRN-XV VCC (Pin 1) – Regulated 3.3V\nRN-XV GND (Pin 10) – GND\nRN-XV TX (Pin 2) – Arduino Serial1 RX\nRN-XV RX (Pin 3) – Arduino Serial1 TX\n \nNote: The RN-XV has 10 pins on each side but some Breakouts like the one I got on RobotShop, have 11.  So be sure you figure which side has the 2 unused pins.  \n \n\nHere’s what it looks like so far.  Ignore the little square board towards the bottom right, that’s a magnetometer which I plan to use later.\nI found the right library for the job with a little help from Tedbot, who has a couple of blog posts on getting started with the RN-XV on his site.  Here he recommends using this WiFly library by jcrouchley.\n\nThere is the start of a “polling client” sketch, where the arduino is repeatedly requesting new data from a server.  The idea is to have the arduino send it’s sensor data to the server via HTTP requests and the response would contain commands that the robot will follow.\n\n#include \"WiFly.h\"\n#include \"MotorDriver.h\"\n\n#define motorAPWM 11\n#define motorAIN1 12\n#define motorAIN2 13\n#define motorBPWM 10\n#define motorBIN1 9\n#define motorBIN2 8\n\nMotorDriver leftMotor = MotorDriver(motorAIN1, motorAIN2, motorAPWM);\nMotorDriver rightMotor = MotorDriver(motorBIN1, motorBIN2, motorBPWM);\n\nWiFlyClient client(\"192.168.1.101\", 800);\n\nvoid setup() {\n\n  Serial.begin(9600);\n  Serial1.begin(9600);\n\n  WiFly.setUart(&Serial1);\n  WiFly.begin();\n\n  Serial1.println(\"set comm idle 2\"); // close an inactive conn in 2 seconds\n  WiFly.join(\"your_ssid\", \"your_passphrase\");\n}\n\nvoid loop()\n{\n  getData();\n}\n\nvoid getData()\n{\n   if (client.available()) {\n    char c = client.read();\n    Serial.print(c);\n  }\n\n  if (!client.connected()) {\n    //delay(100);\n    sendRequest();\n  }\n}\n\nvoid sendRequest()\n{\n  Serial.println();\n  Serial.println(\"connecting…\");\n  if (client.connect()) {\n    Serial.println(\"connected\");\n    delay(100); // seems to prevent an infrequent failed connection\n    client.println(\"GET /robotServer/server.php\");\n    client.println();\n  }\n}\n\nThe PHP code is dead simple at this point.  I am using WAMP as a PHP server hosted on my laptop.\n\n<?php\n  echo 'Robot Server';\n?>\n\nIn your Arduino IDE terminal window you should now see the string “Robot Server” returned every 1 second or so.   Once in a while a request fails.  I’m not sure why it fails, but thanks to the line of code “set comm idle 2″, the failure doesn’t stay open indefinitely and instead closes in 2 seconds on inactivity.  I also noticed putting a short delay here or there greatly reduces the number of failed requests.\n\nAd-hoc Mode\n\nWhen I first tried to make an Arduino program to control the RN-XV, I tried various libraries I found online, none of which seemed to work properly.  Obviously the next step was to RTFM, which in this case was pretty helpful and I was able to make an ad-hoc connection to the module.  What this means is that the little RN-XV can turn itself into a wireless endpoint, which you can use your computer to connect to, just as you would to any wi-fi network.  This part is completely optional (not that the rest is required), it just helps to better understand the capabilities of the module.  Here’s how to use ad-hoc mode:\n\nIn addition to GND, 3.3V, TX, RX, also connect PIO9 (pin 8) to 3.3V\n\nRecycle power, since PIO9 is high, it goes into ADHOC mode\n\nConnect to the “WiFly” ssid from my laptop\n\nTelnet to the IPAddress 169.254.1.1:2000 You should now see HELLO on your telnet screen\n\nType $$$ (with no return carriage).  You shold now see CMD on your telnet screen \n\nPerform the commands (with return carriage after each):\n        set wlan phrase YOUR_PASS_PHRASE\n        set wlan ssid YOUR_SSID\n        save\n        reboot\n\nwhen i did this each letter showed up twice as i typed, but didn’t seem to matter\n\nWhen it rebooted, i lost the connection, but since my CoolTerm window was open, i noticed the RN-XV automatically connected to specified SSID and got an ip. My laptop jumped back to my usual wifi network as well.\n\nI telnet to that new IP\n\nIt should again say HELLO, Again type $$$ and again it says CMD.\n\nNow type “ftp u” and the firmware update is performed using your wi-fi network’s internet access!\n\nNow everytime it powers on, it jumps onto your wi-fi network, and it can turn your arduino into a webserver.  You can try this by typing the IP and port number into a browser like so:\n\nhttp://192.168.1.114:2000","projects":[],"links":{"body":["http://dlnmh9ip6v2uc.cloudfront.net/images/products/10822-01.jpg","http://www.sparkfun.com/products/10822","http://www.sparkfun.com/products/10050","http://www.sparkfun.com/products/8664","http://www.sparkfun.com/products/9132","http://www.sparkfun.com/products/8687","http://www.sparkfun.com/products/9819","http://www.sparkfun.com/products/8276","http://niltoid.blogspot.com/2012/01/magician-chassis-from-sparkfun-is-very.html","http://www.robotshop.com/parallax-breakout-board-for-xbee-module-5.html","https://niltoid.com/blog/rn-xv-wifly/img_20120215_153302.jpg","http://log.liminastudio.com/programming/getting-started-with-the-rn-xv-wifi-module-node-js","https://github.com/jcrouchley/WiFly-Shield","http://www.wampserver.com/en/","http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Wireless/WiFi/WiFly-RN-UM.pdf"]},"media":[{"url":"https://niltoid.com/blog/rn-xv-wifly/10822-01.jpg","alt":""},{"url":"https://niltoid.com/blog/rn-xv-wifly/img_20120215_153302.jpg","alt":"Robot chassis fitted with a breadboard, Arduino and WiFly module"}]},{"slug":"processing-eclipse-android-proclipsoid","title":"Processing + Eclipse + Android = Proclipsoid?","date":"2012-02-06","summary":"Getting a Processing sketch running as an Android app in Eclipse, from SDK and emulator setup to building an APK.","url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/","tags":["tutorial","Processing","Android","Java","Eclipse"],"skills":["Android development"],"themes":["graphics-3d"],"dek":"","bodyText":"Right off the bat I have doubts about using Processing for Android development.  Processing only supports up to Android version 2.2 at this point.  Android is up to 4+ now.  This can’t be good.  But I’m not sure what the repercussions are.  Maybe simple apps will be forwards compatible?  Features like NFC, which only the latest Android versions support, are going to be out of the question, right?  I hope to delve into Android more to answer such questions, but for now I have a few simple steps to get a basic Android app, which leverages Processing, up and running in the Eclipse IDE.\n\nFirst we need to perform steps as documented by Google to get Android up and running on its own.\n\n1.  Install Android SDK.\n\nRun SDK Manager and select the components from the list as follows.  My screenshot says “update” in some places because I last played with Android a year ago.\n\n2.  If you haven’t already, install Eclipse for Java.\n\n3.  Install the Eclipse ADT Plugin.\n\n4.  Create an AVD using Android version 2.2.\n\n5.  Create a blank Android Project again using Android version 2.2.  On the 3rd screen for Package Name, be sure to use something like “com.example.helloandroid” and not “HelloAndroidProcessing” or you’ll get strange errors.\n\n6.  In Eclipse, create a new run configuration using the AVD you created earlier.\n\n7.  Now make sure the Android app runs on its own.  Launch using your new run configuration and you should see the Android emulator pop up.  If you’ve gotten this far, you are ready to develop for Android sans Processing.\n\n8.  If you haven’t already, install Processing (just need to download and unzip).  I’m using version 2.04a.  Stable version 1.5.1 won’t work according to the Processing Wiki.\n\n9.  Now import android-core from your Processing installation.  I created a folder in my new Android project directory called “lib” and placed android-core.jar into it.  Then in Eclipse go to Project -> Properties -> Java Build Path -> Add JARS… and find and select android-core.jar.  (No Proclipsing happening here, though that would be my method of choice for developing Processing in Eclipse for non-Android purposes)\n\n10.  Now make the following code replacement in your main activity class.  Notice I commented out most of what was there by default.  I grabbed a simple Processing sketch from Dan Shiffman’s Learning Processing.\n\npackage com.example.helloandroid;\n//import android.app.Activity;\n//import android.os.Bundle;\nimport processing.core.*;\n\n/*\npublic class HelloAndroidProcessing extends Activity {\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.main);\n    }\n}\n*/\n\npublic class HelloAndroidProcessing extends PApplet {\n    public static void main(String args[]) {\n        PApplet.main(new String[] { “–present”, “something.whatever” });\n    }\n\n    //@Override\n    //public String sketchRenderer() {\n    // return P2D;\n    //}\n\n    PFont f;\n    String message = “this text is spinning”;\n    float theta;\n\n    @Override\n    public void setup() {\n        size(200,200);\n        f = createFont(“Arial”, 20, true);\n    }\n\n    @Override\n    public void draw() {\n        background(255);\n        fill(0);\n        textFont(f);\n        translate(width/2,height/2);\n        rotate(theta);\n        textAlign(CENTER) ;\n        text(message,0,0);\n        theta += 0.05;\n    }\n}\n\nRunning your run configuration should start up the slow slow emulator.  Once I unlock, I see the following:\n\nAlso you will now have a file called HelloAndroidProcessing.apk in your bin folder.  Simply copy it over to your Android device and install it and you’ll see your app in action.","projects":[],"links":{"body":["http://developer.android.com/sdk/index.html","https://niltoid.com/blog/processing-eclipse-android-proclipsoid/androidsdkinstall.jpg","http://www.eclipse.org/downloads/","http://developer.android.com/sdk/eclipse-adt.html","http://developer.android.com/guide/developing/devices/managing-avds.html","http://developer.android.com/guide/developing/projects/projects-eclipse.html#CreatingAProject","https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_1.jpg","https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_2.jpg","https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_3.jpg","http://processing.org/download/","http://wiki.processing.org/w/Android","http://www.learningprocessing.com/","https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_emulator.jpg"]},"media":[{"url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/androidsdkinstall.jpg","alt":""},{"url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_1.jpg","alt":"Eclipse wizard for creating a new Android project"},{"url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_2.jpg","alt":"Eclipse Android project wizard with the Android 2.2 build target selected"},{"url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_create_3.jpg","alt":"Eclipse wizard showing Android application and package settings"},{"url":"https://niltoid.com/blog/processing-eclipse-android-proclipsoid/a_p_emulator.jpg","alt":"Android emulator running the Processing test sketch"}]},{"slug":"impulse-buy-of-the-week","title":"Impulse Buy of the Week","date":"2012-02-03","summary":"An Eitech metal construction kit: an impulse buy that later supplied parts for a robot’s torso and head.","url":"https://niltoid.com/blog/impulse-buy-of-the-week/","tags":["Eitech","prototyping"],"skills":[],"themes":[],"dek":"","bodyText":"","projects":[],"links":{"body":["http://4.bp.blogspot.com/-64DJfYpCLHQ/TyyCFPQJFKI/AAAAAAAAA9U/qYwyHnrqo5c/s720/IMG_20120203_195530.jpg"]},"media":[{"url":"https://niltoid.com/blog/impulse-buy-of-the-week/img_20120203_195530.jpg","alt":""}]},{"slug":"soundground","title":"SoundGround","date":"2012-01-29","summary":"A microphone-reactive Processing sketch with a particle engine, simple 2D physics and an on-screen control panel, developed in Eclipse.","url":"https://niltoid.com/blog/soundground/","tags":["Processing","Java","Eclipse","audio","particles"],"skills":["audio-reactive visuals","physics simulation"],"themes":["sound-visuals"],"dek":"","bodyText":"Graphics programming is a new realm for me and I’ve been searching for the ideal tool sets to use for practice.  Processing is a great way to get started.  Created by Ben Fry and Casey Reas in 2001, it’s a work of art for creating works of art.  It’s incredibly quick and easy to setup, and it’s very satisfying to see your creations moving around on the screen after a few lines of code.  However, the Processing IDE leaves much to be desired, lacking any sort of debugging or intellisense.  Luckily Eclipse is a great free IDE which makes using Processing an even more pleasant experience.\n\nProcessing + Eclipse = Proclipsing\n\nProclipsing makes using Eclipse for Processing very straightforward.  Plus, it allows you to use some powerful Java constructs in your Processing app.  It was recommended to me by my friend Mario (aka OneDayItWillMake) who has been my guide to proclipsing effectively.\n\nSoundGround is a very basic app that responds to mic input.  I used a simple particle engine and modeled some 2D physics.  It’s easier than it sounds, I learned everything from Robert Hodgin’s cinder tutorials a couple years ago.  They are an excellent resource for anyone doing any interactive programming in any language.  Also made use of controlP5, a great library to create a parameter box in Processing.\n\nHere’s the code.","projects":[{"name":"SoundGround151","repo":"https://github.com/asaeed/SoundGround151"}],"links":{"video":"https://www.youtube.com/watch?v=ft6vU5N0LjQ","body":["http://processing.org/","http://benfry.com/","http://reas.com/","http://www.eclipse.org/","http://code.google.com/p/proclipsing/","http://onedayitwillmake.com/blog/","http://libcinder.org/docs/v0.8.3/hello_cinder.html","http://www.sojamo.de/libraries/controlP5/","https://github.com/asaeed/SoundGround151"]},"media":[{"url":"https://niltoid.com/blog/soundground/video-ft6vU5N0LjQ.jpg","alt":""}]},{"slug":"a-dev-blog","title":"A Dev Blog","date":"2012-01-15","summary":"The start of a maker blog: documenting experiments with Arduino and sharing lessons from a community of DIY hackers.","url":"https://niltoid.com/blog/a-dev-blog/","tags":["Arduino","physical computing"],"skills":[],"themes":[],"dek":"","bodyText":"This blog is an attempt to try and document some of my learning experiences.  I’m a web developer by trade and a physical computing hobbyist.  I’ve been exploring the arduino platfrorm for a few years, and it’s incredibly fun to experiment with.  Along the way, I’ve gotten help countless times from an amazing online community of DIY hackers.  Hope this blog returns just a small part of the favor!","projects":[],"links":{"body":[]},"media":[]},{"slug":"robot-chassis","title":"Robot Chassis","date":"2012-01-15","summary":"Building a robot on the Magician Chassis with an Arduino and a dual motor driver, including wiring and a reusable motor-control class.","url":"https://niltoid.com/blog/robot-chassis/","tags":["tutorial","Arduino","robotics","DC motors"],"skills":["motor control","C++"],"themes":["robots-hardware"],"dek":"","bodyText":"The Magician Chassis from Sparkfun is a very good option for a beginner robot.  It’s cheap but not cheapo.  $15 is such a good price, i want to assemble an army of these (Not sure why it’s $28 everywhere else).  Even includes a screwdriver.\n\nIt was dirt simple to assemble, took all of 15 minutes.  The instructions are a little vague, but just remember that the wheel attaches to the side of the motor with the little protruding stub.  You’ll see what I mean when you first try to orient the motors.\n\nThe next day I hooked up a couple of components to the top.  A Sparkfun Arduino Pro 5V and a Polulu TB6612FNG Dual Motor Driver.  After soldering some headers, the Pro easily attaches using some extra hardware that comes with the Magician.  For the Motor Driver, I stuck a mini breadboard to a piece of cardboard and screwed that on with more Magician hardware.\n\nWhen driving DC motors, the standard practice seems to be using separate power sources for the Motors and the Arduino (and everything else).  On an earlier robot  learned this the hard way when I started seeing very strange sensor readings  when a motor kicked in.  I used the 4 AA pack (which came with the Magician) for VMOT, and USB for the Arduino for now.\n\nHook up the Motor Driver as follows:\n\nGND’s to a common ground (Arduino’s GND and GND from motor battery).\n\nVCC to Arduino 5V\n\nSTBY to Arduino 5V (unless you want to control this in code)\n\nVMOT to motor battery pack\n\nAO1 and AO2 to one motor\n\nBO1 and BO2 to other motor\n\nthe rest to your Arduino as the code suggests\n\nPolulu TB6612FNG Dual Motor Driver\n\nHere’s the code, which I found on the Arduino forum here (great stuff cause it’s concise), and then modified and made into a C++ class called MotorDriver.  Check Github for the latest version of the code.\n#include \"MotorDriver.h\"\n\n#define out_A_PWM 11\n#define out_A_IN1 12\n#define out_A_IN2 13\n#define out_B_PWM 10\n#define out_B_IN1 9\n#define out_B_IN2 8\n\nMotorDriver leftMotor = MotorDriver(12, 13, 11);\nMotorDriver rightMotor = MotorDriver(9, 8, 10);\n\nvoid setup()\n{\n  Serial.begin(9600);\n  Serial.println(\"begin\");\n\n}\n\nvoid loop()\n{\n  for (int i=-20; i<20; i++) {\n    leftMotor.setSpeed(i);\n    rightMotor.setSpeed(i);\n    delay(20);\n  }\n\n  leftMotor.setSpeed(0);\n  rightMotor.setSpeed(0);\n  delay(1000);\n}\n\nMotorDriver.h\n\n#ifndef MotorDriver_h\n#define MotorDriver_h\n\n#include \"Arduino.h\"\n\nclass MotorDriver\n{\npublic:\n  MotorDriver(int pinFwd,int pinRev,int pinPwm);\n  void setSpeed(int speed);\n  int getSpeed();\n\nprivate:\n  int _pinFwd;\n  int _pinRev;\n  int _pinPwm;\n  int _speed;\n  int _pwm;\n};\n#endif\n\nMotorControl.cpp\n\n#include \"Arduino.h\"\n#include \"MotorDriver.h\"\n\nMotorDriver::MotorDriver(int pinFwd,int pinRev, int pinPwm)\n{\n  pinMode(pinFwd, OUTPUT);\n  pinMode(pinRev, OUTPUT);\n  pinMode(pinPwm, OUTPUT);\n  _pinFwd = pinFwd;\n  _pinRev = pinRev;\n  _pinPwm = pinPwm;\n}\n\nvoid MotorDriver::setSpeed(int speed)\n{\n  _speed = constrain(speed, -100, 100);\n  _pwm = map(abs(_speed), 0, 100, 50, 255);\n\n  if (_speed > 0)\n  {\n    digitalWrite(_pinFwd, HIGH );\n    digitalWrite(_pinRev, LOW);\n  }\n  else if (_speed == 0)\n  {\n    digitalWrite(_pinFwd, HIGH);\n    digitalWrite(_pinRev, HIGH);\n  }\n  else if (_speed < 0)\n  {\n    digitalWrite(_pinFwd, LOW);\n    digitalWrite(_pinRev, HIGH);\n  }\n\n  analogWrite (_pinPwm, _pwm);\n}\n\nint MotorDriver::getSpeed()\n{\n  return _speed;\n}\n\nI’ve realized that the Arduino Pro is not going to have enough pins.  Just this 1 component takes up almost half it’s digital pins.  I could try a 8-bit shift register, but it will take up precious space and I’ll have to keep adding more. Instead, I decided to swap out the Pro for a Mega.\n\nAnother modification, I replaced the screws holding the battery pack with one of my favorite prototyping tools – velcro.  This will make it easier to replace batteries.","projects":[{"name":"WiFiRobot","repo":"https://github.com/asaeed/WiFiRobot"}],"links":{"body":["https://niltoid.com/blog/robot-chassis/img_20120114_163743.jpg","http://www.sparkfun.com/products/10825","http://www.sparkfun.com/","http://www.sparkfun.com/products/9219","http://www.pololu.com/catalog/product/713","https://niltoid.com/blog/robot-chassis/img_20120115_105030.jpg","https://niltoid.com/blog/robot-chassis/0j927.200.jpg","https://niltoid.com/blog/robot-chassis/img_20120115_105051.jpg","http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1263858213","https://github.com/asaeed/WiFiRobot","https://niltoid.com/blog/robot-chassis/img_20120115_105430.jpg","https://niltoid.com/blog/robot-chassis/img_20120115_134928.jpg"]},"media":[{"url":"https://niltoid.com/blog/robot-chassis/img_20120114_163743.jpg","alt":""},{"url":"https://niltoid.com/blog/robot-chassis/img_20120115_105030.jpg","alt":"Arduino robot chassis with breadboard and wiring"},{"url":"https://niltoid.com/blog/robot-chassis/0j927.200.jpg","alt":"Motor driver breakout board with labeled control and power pins"},{"url":"https://niltoid.com/blog/robot-chassis/img_20120115_105051.jpg","alt":"Close-up of the Arduino board and wiring on the robot chassis"},{"url":"https://niltoid.com/blog/robot-chassis/img_20120115_105430.jpg","alt":"Side view of the robot chassis showing its wheels and electronics"},{"url":"https://niltoid.com/blog/robot-chassis/img_20120115_134928.jpg","alt":"Assembled two-wheel robot chassis viewed from above"}]}]}