Wednesday, May 1, 2013

Lighting LEDs on the Raspberry Pi with Python

There are many tutorials available for this already, but I just wanted to collect my observations into a series of steps that I can repeat later.

For reference, I used raspberry-gpio-python, Raspberry Leaf, and How to use your Raspberry Pi like an Arduino.

I connected an LED and an inline resistor to GPIO pin 7 and ground, one side of a momentary pushbutton to ground, and the other side of the pushbutton to a 1 kOhm resistor connected to 3.3 V.

Starting from a fresh install of Raspbian, at the command line (or in LXTerminal) input the following -commands: (edit: the crossed-out commands aren't really necessary)

sudo apt-get update
sudo apt-get install python
sudo apt-get install python-dev
sudo python distribute_setup.py
sudo easy_install pip
sudo apt-get install python-rpi.gpio

sudo python


#!/usr/bin/env python
from time import sleep
import os
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

# define the pins we're using
button1 = 4
LED = 7

set up the pins
GPIO.setup(button1, GPIO.IN)
GPIO.setup(LED, GPIO.OUT)

# turn on the LED
GPIO.output(LED, True)
# wait for half a second
sleep(0.5)
# turn off the LED
GPIO.output(LED, False)
# toggle the LED
GPIO.output(LED, not GPIO.input(4))

# set up some variable to read from the button
input = False
previousInput = True

# loop
while True:
 # read the button state to the variable input
 input = GPIO.input(button1)
 # make sure the button state isn't what it used to be
 if ((not previousInput) and input):
  print("button pushed")
 # copy the button state to the previousInput variable
 previousInput = input
 # wait to "debounce" the input
 sleep(0.05)

# clean things up
GPIO.cleanup()

Vectorizing a Scanned Object for CNC Cutting

If you have a physical object or paper drawing that you'd like to carve out using a CNC router or plasma cutter, here's one way to do it. We're going to use the open source drawing program Inkscape for turning scanned images into vectors that the machine can cut.

Start by scanning the object (or drawing) on a flatbed scanner. If you don't have access to a scanner, you can try taking a picture from directly above the object (or the drawing). For this example I've scanned a handheld wireless microphone.
This will be a somewhat complicated image to vectorize, it would be better if it was simply black and white (like a line drawing or most logos). The nice thing about how this scanned, though, is that the background is totally white. Don't worry if yours isn't, that's something we can deal with or fix later.

Start up Inkscape (you can download the portable version if it's not installed on your computer) and under the File menu choose Import... and find the image that you scanned earlier. It doesn't matter if you link or embed, since you'll be removing the image from Inkscape soon anyway.

Now it's time to turn that image into a vector outline. Make sure that the image is selected, and under the Path menu choose Trace Bitmap... to bring up the following window.

Experiment with changing the Brightness cutoff Threshold. I tried values of 0.4, 0.6, 0.8, and 0.9 to get the following vectors (from left to right, with the original bitmap image on the far left).

Each time you click OK it will create another vector object, which you can delete if you don't like it. In my example above there's a little white spot that shows up even at high threshold values, so that's something that I could go back to the original image and paint over, or I can break apart the vector group and delete the parts that I don't want. (Under the Path menu choose Break Apart, then delete everything you don't want).

After all of that, we end up with a fairly good outline of the object.

You can also experiment with the Simplify command under the Path menu, each time click that it will remove some points from your vector.

Depending on the resolution that you scanned at, you will probably have to resize the vector to make it the size of the actual object. Make sure the lock is engaged (to maintain the proper aspect ratio) and the units are in inches (or mm if you prefer). Typing a value in the width (W) will change the height (H) and vice versa.
So we have now vectorized the scanned image, and it's ready to be saved and then imported into your favorite CAM program to generate g-code for your machine. Or you can use the Gcodetools plugin for Inkscape.

Thursday, April 25, 2013

iPad app: Entrepreneurship Essentials course


ADLCRobots and Pencils, and GoForth Institute have developed an iPad app that teaches Entrepreneurship Essentials. Through the simulation of running a lemonade stand, it uses gamification principles, text slides, videos, and auto-graded quizzes to deliver the content for five one-credit CTS courses (ENT1010, 1020, 2010, 2020, and 2030).

It is fairly well designed, certainly better than most LMS-based online courses. Students will still need to be somewhat self-motivated to make it through, but the badges, notifications, and challenges should help.

From what I hear, schools that register students in this "course" can receive all of the CEU funding if they have a teacher assigned to do the "marking" and tracking, or they can receive 3/5 of the funding if they get ADLC to do all of that.

There has been some media coverage by CBC News and the Edmonton Journal. If you're interested, check out more information and an introduction video.

At any rate, I'm certainly going to recommend it to high schools that have students interested in entrepreneurship and/or interested in trying a different method for getting CTS credits. Information about registration is here.

Thursday, April 11, 2013

things I've learned about Source Filmmaker

I've been playing with Source Filmmaker a bit lately, and I wanted to document some of the things that I've learned.

The best source of information is the official SFM wiki.

There are also numerous video tutorials available on YouTube, including the official ones.

The up and down arrows take the playhead to the beginning and ending of a shot, respectively.

Audio should be in WAV format. And I recommend using a nice USB microphone for recording audio.

More models and props can be downloaded (subscribed) from the Steam Workshop. I was particularly interested in models with facial animations for lip-sync, and there are a number available there.

Attach a prop (e.g. a hat) to a character's head by locking it to the bip_head control in the character's animation set. Drag the character's bip_head control on to the hat's bip_head (or rootTransform) control, then select all of time in the Motion Editor (if it's not all green already), select the Body animation set of your prop and then under Procedural drag the Default control from left to right. You may need to adjust its position a little, especially if you used rootTransform because there was no bip_head.

Attach a prop to a character's hand by locking it to the weapon_bone under Unknown in the character's animation set. Similar to the above process.

In order to render 1080p videos, you need to start the program with the argument -sfm_resolution 1080 (either from your Steam library by right-clicking it and choosing Properties then SET LAUNCH OPTIONS... or by editing the desktop shortcut). This isn't recommended until you're ready to render, since working in 1080p makes things a little slow. Rendering 1080p videos takes a long time too, on my i7 desktop it took almost an hour and a half to render a one minute clip. If you're really adventurous you can render at 4K with -sfm_resolution 2160 but you'll need a decent computer a lot of time.

The basic process I go through to create videos (like the one below) is:
  1. launch Source Filmmaker
  2. name your session (or open an existing session)
  3. set the Framerate to 30 (although the default 24 is fine too)
  4. right-click the black part where it says "No Map Loaded!" and choose Load Map...
  5. decide where you'd like to film
    • you can move the camera around by holding down the mouse button where you'd just loaded a map (the viewport) while you use the keys WASD and ZX
  6. click the + sign right underneath Animation Set Editor to Create Animation Set for New Model
    • look in the categories player and survivors for good human models
  7. move the model to the appropriate place by selecting its name in the Animation Set Editor, the move tool  (near the bottom right of the map window) and either the Motion Editor (F3) or the Graph Editor (F4)
  8. add a camera by pressing c on the keyboard
    • or click the down arrow on the right of the active camera button (below the viewport), click Change Scene Camera, and click New Camera.
  9. click the + sign to Create Animation Set(s) for Existing Element(s) and choose camera1 so that you can animate that camera
  10. add any props and position them how you'd like
    • the same way that you added a new model in step 6
    • if you want them to move with a character, make sure you lock them to that character (e.g. their weapon_bone or bip_head)
  11. add your recorded voice clip by selecting the clip editor (F2), right clicking on Dialog (near the bottom), and choosing Add Clip to Track or Record Narration
    • when you are adding a clip to a track, any WAV files that are in the ...\steam\steamapps\common\sourcefilmmaker\game\usermod\sound file will show up
  12. to have your character move their lips along with the voice track, select the Dialog track, the character's Lower Face (and Tongue) in the Animation Set Editor, right-click in the Animation Set Editor, and choose Extract Phonemes
  13. I usually animate the camera by moving it around rather than using the fieldOfView control
So that is a very brief overview of some of the things I've done in Source Filmmaker so far. Here's an example of one I did recently:

Monday, April 8, 2013

installing Red5 in Ubuntu from the command line

First install the requirements for Red5:

sudo apt-get install java-package openjdk-7-jre openjdk-7-jdk ant subversion

Next download and untar Red5:

tar xvfz red5-1.0.0.tar.gz

Rename the folder:

mv red5-1.0.0 red5

And then run Red5:

cd red5
sh red5.sh

After scrolling through a lot of verbose information about the startup of Red5, you'll know it's running when you see the line that ends with Installer service created.


If you're browsing from the computer that it's installed on, you can see if the Red5 server is running by going to http://localhost:5080 .

Monday, January 28, 2013

Google script to email form data

I helped someone set up a Google Form with email notifications the other day. This morning they asked if they could be emailed the submitted data, rather than just a link to the spreadsheet. Since there's only one question on the form, that's an easy script:


function onSubmit(e) {
  var timestamp = e.values[0];
  var question1 = e.values[1];
  var address = "firstaddress@example.com, anotheraddress@example.com";
  var subject = "Feedback form submitted";
  var body = "Someone submitted the form at " + timestamp + " and said " + question1;
  MailApp.sendEmail(address, subject, body);
}


This script will send an email to the address(es) in quotes after the var address = . The body of the email will contain the string that is in quotes after var body =  , which includes the timestamp (from column A of the spreadsheet) and what the user submitted in the form (the contents of column B).

To get this to work for you, paste the above code into a new blank script that's associated with a form you've created, and then set up a trigger that runs the function onSubmit(e) when the form is submitted.

To set up the trigger, follow the instructions from this page:


  1. Open or a create a new form, then go to the results spreadsheet of that form.
  2. Click the Unsaved Spreadsheet dialog box and change the name.
  3. Choose Tools > Script Editor and write the function you want to run.
  4. Choose Resources > Current script's triggers. You see a panel with the message No triggers set up. Click here to add one now.
  5. Click the link.
  6. Under Run, select the function you want executed by the trigger.
  7. Under Events, select From Spreadsheet.
  8. From the next drop-down list, select On form submit.
  9. Click Save.
Of course if you have more than one question in your form, you'll need a variable for each of them (e.g. var question2 = e.values[2];) and you'll need to call those variables in the var body =  statement.

Let me know if this works for you.

Thursday, January 24, 2013

automatically adding column data to google form submissions with a script


I've often come across the issue of wanting to manipulate data that has been submitted with a Google Spreadsheets Form. For example, automatically marking and totaling formative quizzes where students submit their answers in a Google Form.

Unfortunately when a user submits a form, a new row with those data is inserted on the spreadsheet. This means any formulas that you've manually added to the Spreadsheet will be above or below that row.

To solve this issue, I wrote a Script that copies (to that inserted row) the contents of the columns you've added in the first row.


function addFormula() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 2;
  var startColumn = 8;
  var numberRows = 1;
  var numberColumns = 15;
  var lastRow = sheet.getLastRow();
  var sourceRange = sheet.getRange(startRow, startColumn, numberRows, numberColumns);
  var destinationRange = sheet.getRange(lastRow, startColumn, numberRows, numberColumns);
  sourceRange.copyTo(destinationRange);
};


The meanings of the variables are:
sheet is a shortcut so we don't have to keep typing SpreadsheetApp.getActiveSheet()
startRow is the row number that's the source of your formula that you want to copy
startColumn is the column number where your source formula starts
numberRows should usually be 1, it's the number of rows that you would like to copy each time
numberColumns is the number of columns that contain your source formula
lastRow is a shortcut so we don't have to type sheet.getLastRow() when we want to use it
sourceRange collects together the information to tell copyTo where to get the data
destinationRange collects together the the information to tell copyTo where to put it


If you prefer, this could also be done in a single line without all of the variable declarations:


function addFormula() {SpreadsheetApp.getActiveSheet().getRange(2, 8, 1, 15).copyTo(SpreadsheetApp.getActiveSheet().getRange(SpreadsheetApp.getActiveSheet().getLastRow(), 8, 1, 15))};


To add this script to your spreadsheet of data from a Google Form
  1. open the spreadsheet and under the Tools menu choose Script editor...
  2. under "Create script for" click Spreadsheet
  3. delete everything in the Code.gs pane and replace it with the script from this blog post
  4. if necessary, change the numbers for the variables to what they should be for your spreadsheet
  5. under the File menu click Save
  6. under the Resources menu click Current script's triggers...
  7. if you haven't already named your project, do so now in the box that comes up
  8. click No triggers set up. Click here to add one now.
  9. in the third drop-down list, select On form submit
  10. click the Save button
And you're done. The script will run whenever a user submits the form, and it will copy the formulas that you've set up on the first line of submitted data. Leave a comment below if this works for you or if you have any questions.