by on Arduino

Once again find myself in a windowless cube. So I 3d printed a varient of a compact camera gimbal and attached an rpi camera to it.  I needed to set up a serial based protocol to talk to it. Its a pretty good example of creating your own protocol as described in the Physical Computing book. The gimbal is servo based and there is one servo for rotation or “yaw” and one for attitude or “pitch”. So the protocol I came up with was:

yXXX<cr>
pXXX<cr>

where XXX represents a number between 0 and 180 (servo values)

Here is the code.


/*
  demonstration of a private protocol.
  we have a serial connected device that has two servos attached to it. 
      one controls the pitch (up and down) 
      one controls the yaw (round and round)
  we send it lines of text in the form 
  s<cr>
  where s is:
    pnnn -- pitch value (0-180)
    ynnn -- yaw value (0-180) 
  Normally it doesnt respond unless weWANNADEBUGTHIS or if it doesnt understand us
  in this case it replys with ?????
 */

#include <Servo.h>
#include <stdlib.h>

#define YAW_PIN 10
#define PITCH_PIN 9
#define YAW_HOME 60

#define PITCH_HOME 35
#define MAXCHARS 10
//#define IWANNADEBUGTHIS 1
#ifdef  IWANNADEBUGTHIS
#define HEY_ARE_YOU_LISTENING_TO_ME 1
#define HEY_I_AM_TALKING_TO_YOU 1
#endif

Servo yaw;
Servo pitch;
char inputBuffer[MAXCHARS];
boolean inputBufferReady;
int inputBufferIndex;

void setup()
{
  // initialize the serial communication:
  Serial.begin(9600);
  yaw.attach(YAW_PIN);
  pitch.attach(PITCH_PIN);
  yaw.write(YAW_HOME);
  pitch.write(PITCH_HOME);

}

boolean gotDataLine (void){
  char inch;
  if (inputBufferIndex>=MAXCHARS) {
    inputBufferIndex=0;
  }
  if (Serial.available()){
    inputBuffer[inputBufferIndex++]=inch=Serial.read();
    inputBuffer[inputBufferIndex]='\0';
    //Serial.print("I received: "); Serial.println(inch);
    if ((inch == '\n') && (inputBufferIndex>0)) {      // I dont want this charachter
      inputBufferIndex--;    // "dtmfa" - dan savage
      return false; 
    }
    if ((inch == '\r') && (inputBufferIndex>1)) {
        inputBuffer[inputBufferIndex-1]='\0';
        inputBufferIndex=0;
        return true;
    }
  }
  return false;
}

void loop() {
  int myValue;
  if (gotDataLine()) {
    myValue=atoi(inputBuffer+1);
    if (myValue>180) myValue=180;
    if (myValue<0) myValue=0;
    switch(inputBuffer[0]) {
      case 'p' : 
#ifdef HEY_ARE_YOU_LISTENING_TO_ME
                 Serial.print("Setting pitch to ");
                 Serial.println(myValue);
#endif
                 pitch.write(myValue);
                 break;
      case 'y' : 
#ifdef HEY_ARE_YOU_LISTENING_TO_ME
                 Serial.print("Setting yaw to ");
                 Serial.println(myValue);
#endif
                 yaw.write(myValue);
                 break;
      default:  Serial.print("?"); Serial.print(inputBuffer); Serial.println("????");
    }
  }
}

 

by on Arduino

I have been teaching Physical Computing for Artists with the Arduino Uno for over a year now and this year I decided to move to the Leonardo with the hope that a USB-Midi based core will be finished sometime soon. Its cheaper than the uno and it has a serial port that isn’t busy and best of all it doesn’t reboot every time you talk to it.

I usually introduce background tasks using the Timer1 library since it makes timers manageable for the novice. However the existing Timer1 and Timer3 libraries are not currently avaliable for the leonardo (or any of the 4 32u4 based processors). Fortunately there is a “port” of the library for the Teensy2.0 at http://www.pjrc.com/teensy/arduino_libraries/TimerOne.zip, for some reason the leonardo is missing from the boards supported but no matter the fix is pretty easy and now I can get back to teaching.


diff ~/Downloads/TimerOne/config/known_16bit_timers.h TimerOne/config/known_16bit_timers.h 
11,22c11,34
< 
< // Teensy 2.0
< //< 
< // Teensy 2.0
< //
< #elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
<   #define TIMER1_A_PIN   14
<   #define TIMER1_B_PIN   15
<   #define TIMER1_C_PIN   4
<   #define TIMER1_ICP_PIN 22
<   #define TIMER1_CLK_PIN 11
<   #define TIMER3_A_PIN   9
<   #define TIMER3_ICP_PIN 10
< 
---
> // mega34u4
> // Ehem: it would be nice to figure out the sparkfun micro-pro
> // and the adafruit u4 stuff as well.
> #elif defined(__AVR_ATmega32U4__) 
>     // Teensy 2.0
>     #if defined(CORE_TEENSY)
>         #define TIMER1_A_PIN   14
>         #define TIMER1_B_PIN   15
>         #define TIMER1_C_PIN   4
>         #define TIMER1_ICP_PIN 22
>         #define TIMER1_CLK_PIN 11
>         #define TIMER3_A_PIN   9
>         #define TIMER3_ICP_PIN 10
>     // otherwise assume Leonardo/micro/esplora
>     #else 
>         #define TIMER1_A_PIN   9
>         #define TIMER1_B_PIN   10
>         #define TIMER1_C_PIN   11
>         #define TIMER1_ICP_PIN 4
>         #define TIMER1_CLK_PIN 12
>         #define TIMER3_A_PIN   5
>         #define TIMER3_ICP_PIN 13
>     #endif
> 

http://www.suspectdevices.com/reference/Timer1.tgz

by on Open Hardware Summit

The Open Hardware Summit is becoming my favorite event of the year. It’s a great cross-section of what people are doing with hardware. I had submitted a talk about ethics and labor in computing, but the talk was rejected. I didn’t feel bad about it because I was confident that the organizers would pick a good mix of speakers this year. I was completely right! The keynote this year was given by Eben Moglen who stressed to us the importance of open hardware and software as a means to help our communities and as a potential tactic in unfolding capitalism. This spirit seemed to continue through the conference, although not completely since the OSHWA membership is largely pro-capitalist.

Around the conference I got to meet Don’s friends from ITP Summer Camp. Everyone from that group is doing interesting things. I got to talk about Nintendo stuff, as I did a Nintendo-themed art piece earlier this year. Jonathan Dehan showed me his work in helping people make their own ROM hacks of Super Mario Bros.
Super Mario Bros Clouds

The big lesson this year was learning how to be tactful. I ran into my ex-employer a lot, which was awkward, so I had to pull up a lot of courage to even address it and apologize for being rowdy previously. I had hoped for an apology from him, but I realize that it will never happen and I had to be the better person. I think I grew a bit personally.

I was most excited about the women’s dinner that followed the summit. I am not usually one to go to all-women’s events but considering that most of the organizers and key players of the open hardware movement are women, I thought I’d go. I’m glad I did! I had so many wonderful conversations with everyone. It was actually very comfortable to finally talk shop without the weird overhead and baggage that can come from being in a mixed space. I met a friend’s roommate by accident who told me about PCBmodE. I also met Erin aka RobotGrrl who suggested I try out gEDA. I got to talk to people who were going to China to see how the work conditions are, and I talked to other artist-hackers. Overall I had a really positive experience this year.

See all my snapshots on Flickr!

by on Arduino

Arduino for Artists.

(The class formerly known as Physical Computing for Artists)

During the summer break Donald Delmar Davis went to ITP Summer Camp 30 days of more intersection between art and technology than anyone can take in. He is hoping that he can use what he learned to teach more artists about how to integrate the arduino into their tool set. This year he will be working with the Arduino Leonardo with the intention of bringing midi and other usb clsses into the Arduino’s capabilities.

https://cereg.pnca.edu/p/adult/s/407

Tube Amplifiers.

During the summer Mark Keppinger piloted a new class that he is offering this fall. In the class you get to build and take home a tube amplifier (for your guitar, iPhone/iPod, etc). This includes both the electronics and the cabinet to hold it.

https://cereg.pnca.edu/p/adult/s/405

by on Site News

A while ago I posted an opinion about sharing and the point of openness. It was intended to be focus of conversation and so I took a stance that was controversial and was thoroughly attacked for it. It happens a lot more that we would like. A few months later I overheard Bre Pettis talking about physical threats of violence over not completely opening the hardware designs for his product. I understood both sides of the argument however I could not understand the state of our world in terms of its inability to have real discourse with compassion and respect without hatred and violence. Reading the comments section of almost any major news or opinion piece or even hanging out in the average technical IRC channel makes me want to cry.

And so I stopped sharing and posting, withdrew and shut down.

But its still all out there effecting people I love and respect. This internet thing seems to have no filters, knows no bounds in its capacity to hurt people with things that they have no control over. Even as I stop participating the conversations and ugliness come around through the people close to me.

Somehow we’ve got to be better than this as people.

Starting with me.

I realize that I can be harsh and opinionated. I have said some things over the course of the years that I am ashamed of and I am sorry.

I am working on that.

I hope to be less judgmental and more constructive as I try to promote the projects that I care about and share what I learn along the way. I think you will find me very hesitant to have a personal opinion but I believe that is just the nature of the beast. I hope that someday we can learn to have opinions and constructive dialog out here on the net without tearing each other down.

In the mean time I am trying to open up again.

 

 

by on ITP Summer Camp.

After having a nice post meet and greet dinner out on St Marks street with fellow campers last night I was woken up by one of my dorm mates at 7 am. He is doing an internship at Goldman Sachs. I had so much on my mind I wanted to jump up and write it down in my sketchbook but I realized that I misplaced it. I could not go back to sleep until 11. At noon I woke to a text from my friend Eva one of my favorite artists who is also the person who told me about ITP summer camp (she is alumni) for an invite to lunch down in the heart(bowels?) of the city’s government. After consulting the googles for initial transit directions I was only lost for about an hour. (Lesson: use a map and pay attention to where you are). I was late and the food was expensive for no good reason but that wasn’t the point, the point was to see my friend, which was awesome .

Eva pointed me at several resources and told me about the figment project on governors island where she is taking her inflatable cowfish sparky to this weekend. After a nice visit I walked to Broadway and then up to Canal Street where I followed up on last years global geek walking tour of New York from the open hardware summit. I stopped at a few over priced electronics shops and the two remaining canal street electronics surplus shops that I remember from my first trip to NYC in the mid 80s (Argo electronics and (269) Electronics Inc).

I bought some awesome stomp switches.

In between them I found Canal Plastics where I picked up some material to learn to cut with the laser cutter.

By this time it was late in the afternoon so I took the train from broadway and canal to 8th and got a locker for my new found materials and hydrated several times before going to the bookstore for another sketchbook and to check out the electronics selection at the computer store (I realized I was going to have to mail order or dig around for what I need in the next few weeks).

By that time it was time for the max/msp/jitter class. I wanted to take all of the classes today but they were all overlapping. So I went to the max class. I realized that most of what I knew about PD translated roughly to what Scott was teaching though it was nice getting a comparison and contrast. Fortunately the meat of what I really wanted should be covered on Thursday.
So I snuck off to the pop up books. I probably would have not done this but 1. part of the point of this camp is to do things I wouldn’t do and, 2 I had a student this year who’s project proposal was to build exactly this kind of book for his newborn.

testnewbie

Ms. Jenkins started off with a presentation which kicked all powerpoints in the keaster. Not only would I would have loved to see the talk that she says started her down this path but I thought it moved the consciousness beyond the ordinary and therefor totally met Dick Ibach‘s criteria for good art. I am especially glad that she gave us the links for the works of Jie Qi and the other things she claims to have stolen. (I teach my students that in physical computing you do not steal, you share, and if you make them work for you, you own them….) I am pretty sure I can reconstruct the second half of her class but it was extremely hard to leave for the Processing class. I was not alone in wanting to take this particular class since when the max class got out we had to move to the larger room and by the time it was done I was completely spent. Part of me was still trying to figure out if it would have been better if the classes had been spread out. I decided I had just had the best of all possible worlds. After having a beer and watching Pa(h?)r start his cb550 I went back to where I ate last night. My sketchbook was still there. It was the perfect end to an awesome day ..

by on Arduino

Watch while I pull another race clock system out of my hat.

A couple of years ago Rapha gave me the mechanical race clock that I helped build for them 5 years ago and its been laying around in my pile since then. Three weeks ago Chrome bags called me up and asked if they could take it with them on a 4 month promotional tour. There wasn’t time to build out new hardware but I told them if they bought the open sprints sensor hardware we could work something out.

The first week was spent paring the device down from 4 bikes to two bikes. Two of the driver boards had issues and the shaft on the smallest dial was bent so it is a good thing they only wanted 2. The bushings on the last two dials needed to be cleaned up since they were binding. This is not my strength but I was able to figure it out.

While I was waiting for the sensors I built a test rig like the one that I just threw away from a pair of cds mounted on motors driven by a trusty L293D This time I put it in a box so that it might survive between use.

Once we got the open sprints gear we got down to the fun part.

I had done a sensors only setup for Chrome several years ago. Getting the setup to work using serial and ruby on the Macintosh was really painful and I can see pretty clearly why they have since dropped the support for the old software and gone with a flash based software  written by a third party called Goldsprints_FX. Since flash doesn’t talk to serial devices the sensors on the arduino based open sprints are proxied to a network connection using serproxy or “tinkerproxy”. I could not find the source code for tinker proxy so I went with the serproxy.

Proxying the Proxy.

What I needed to do was to intercept the sensor values from the opensprints arduino based hardware and the go and reset values from the goldsprints software. I started looking at the source code for the serproxy and making a network tap, then I experimented with socat. Both of which seemed too complicated. Finally I went back to the python in a nutshell book and mangled the socket in and out samples into a very simple proxy. The proxy passes data from 5330 (which is where serproxy is sending the serial data) to and from 5331 which is where goldsprints_fx expects the serproxy to be.

import socket
import re
isocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
osocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
isocket.connect(('localhost',5330))
isocket.settimeout(0.2)
print "Connected to serproxy"
osocket.bind(('',5331))
osocket.listen(1)

try:
    while True:
        connection,address=osocket.accept()
        if not connection: break
        print "Connected From", address
        connection.settimeout(0.2)
        while True:
            try:
                receivedData = connection.recv(8192)
            except socket.error:
                receivedData=None
            if receivedData is not None:
                # print ">"+re.escape(str(receivedData))+">"+str(len(receivedData))
                isocket.sendall(receivedData)
                for chunk in receivedData.split('\x00'):
                    if len(chunk)>0 and chunk[0] == 's':
                        print "(RE)SET RACE !!!"
                    if len(chunk)>0 and chunk[0] == 'g':
                        print "GO !!!"
                if len(receivedData)==0:
                    print "ISSUE WITH CLIENT"

            try:
                sentData = isocket.recv(8192)
            except socket.error:
                sentData=None
            if sentData is not None:
                #print "<"+re.escape(str(sentData))+"<"+str(len(sentData))
                connection.sendall(sentData)
                for chunk in sentData.split('\x00'):
                    #if len(chunk.rstrip('\r')):
                    #    print "<",re.escape(chunk),len(chunk)
                    if len(chunk) > 4 and chunk[0]=='0' :
                        done1=int((float(chunk[3:])/1566.0) * 100.00)
                        print "Bike # 1 is ", str(done1), "percent done"
                    if len(chunk) > 4 and chunk[0]=='1' :
                        done1=int((float(chunk[3:])/1566.0) * 100.00)
                        print "Bike # 2 is ", str(done1), "percent done"
                if len(sentData)==0:
                    print "ISSUE WITH SERPROXY"

finally:
    connection.close()
    osocket.close()
    isocket.close()

The print statements which are commented out above allowed me to see both sides of the conversation while picking out the pieces that I needed. This works pretty well at getting the data.

$./serproxy.py
Connected to serproxy
Connected From ('127.0.0.1', 61571)
(RE)SET RACE !!!
(RE)SET RACE !!!
GO!!!!!!!!!!
Bike # 1 is  0 percent done
Bike # 2 is  0 percent done
...
Bike # 1 is  100 percent done
Bike # 2 is  100 percent done
(RE)SET RACE !!!
$

To make this drive the clock required retooling the clock code a bit and configuring serproxy. Since the opensprints uses the old ftdi based arduino the name of the device on the Macintosh is unique to the does not change. I bought a pair of sparkfun “red boards” and also added proxies for the clock and the test rig. Now the code to talk to the clock is the same as talking to the other network sockets. On top of that I can telnet to the test rig and set the “bike” speeds.

Once this was working I also modified the opensprints basic_msg code to provide more frequent updates since the clock is rather jerky when it gets new positions every 250ms. Cutting it to 50ms eliminates most of that, as you can see from the video below.

The current version of the code starts serproxy and Goldsprints_fx and kills them when done it is posted at https://github.com/suspect-devices/bikewedge/blob/master/RetoolingForOpenSprints/bin/bikewedge.py. The entire project including the 3 arduino sketches, serproxy source code and configuration file and the bikewedge proxy can be found at https://github.com/suspect-devices/bikewedge

by on electronics

Most of this week has been devoted to finishing the house network setting up a workspace in the garage and using it. One of the things I have been trying to get off of my plate was to rebuild the transit tracker that we use to tell us when the next max is going downtown. In order to network from the house to the garage I have to navigate a super creepy crawl space and not get spider bitten or set up a wireless bridge. One of the OpwnWrt devices we bought to evaluate seemed perfect. The TP-Link TP-WR740.

 

Getting the OpenWrt operating system on the router is pretty much a matter of uploading the new firmare ( http://downloads.openwrt.org/attitude_adjustment/12.09-beta/ar71xx/generic/openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-factory.bin) using the routers web based interface. Accessing the serial port required some surgery.

 

Once the serial was connected to the 4 pin connector I tested it with my ftdi.3.3v serial cable. Then I tried to see if the 3.3v tx signal was strong enough to be read by a sparkfun 5v serial lcd board I had on the bench. It wasn’t. If i had the parts for the 3.3v-5v boards i had fabbed last month (in particular the 74ahc125) then I would be done. So I looked around for what I could find. One of the documents I found on this was an app note from microchip called “3V Tips and Tricks” (http://ww1.microchip.com/downloads/en/DeviceDoc/chapter%208.pdf). As I was looking through it I went out to the garage and tried to see what I had that I could use. In a box labeled “chips and dips” I found a bunch of lm393 comparators that I had been packing around for over 10 years.

So I soldered an lm7805 to the dc coming in and the ground-plain started breadboarding.

I got no love from the resistor values provided by microchip so I put a pot in place opened a minicom connection to the serial on the router, held my hand on the g key, and rotated the pot until I got ggg’s on the lcd. Then I continued until I stopped getting characters. Then I centered the pot in between those places pulled it out and measured it with a multimeter. Which gave me the circuit below which I wired up bug style and embedded in hot glue.

 

There was still a little work to do. The OpenWrt luci system takes up a lot of space but makes trying things very easy. The command line tools aren’t bad but luci comes with most of the stock images which is ok. The thing that forced me to build a custom image was that the fact that the serial port starts up at 115200 baud rate and my lcd module didn’t support that. To make matters worse sending the boot messeges at 115200 created serial sequences that would corrupt the lcd module.

To get the baud rate to 9600 required me to:

  • Upload the OpenWrt-ImageBuilder-ar71xx_generic-for-linux-i486.tar.bz2 to one of my linux machines.
  • Find and replace parts of the Makefile where the console baud rate was hard coded. (target/linux/ar71xx/image/Makefile)
  • “make image” with the correct target and any packages I wanted installed.

I also commented out the install luci part in the .config file at the top of the tree and added the trimet.lua script to a /scripts directory and which was magically added to my custom image (though not were I expected it to be).

make image PROFILE=TLWR740 PACKAGES="nano coreutils-stty coreutils-nohup monit lua luasocket" FILES="myscripts"

This created several images including one called bin/ar71xx/openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-sysupgrade.bin
to install it i scp’d it to the /tmp/ partition of the router sshd into it and as root ran the command.

root@fatlink:~# sysupgrade -v openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-sysupgrade.bin

where as the router flashed the image and rebooted.
A little tweeking on the startup scripts and we were done.

IMG_1545

The transit tracker code from my previous post runs while the router is still doing its job as a hub and a wireless router.

Not bad for 20 bucks and what we had on hand.

References:

 

 

by on Maple Bacon

As an example of a project for last fall’s “Physical Computing for Artists” class I suggested a light switch based on one of Stephen Wrights comedy bits.

‘In my house there’s this light switch that doesn’t do anything. Every so often I would flick it on and off just to check. Yesterday, I got a call from a woman in Germany. She said, “Cut it out.”‘ — Steven Wright

Using one of the bacomatic5000s I created a light switch that posts its state to the web. The idea is that like the switch in Stephen’s apartment there is no connection between turning the switch on and off and what it effects. You can connect your “things of internet” (ToI ™) to the switch by polling http://www.suspectdevices.com/art2013/swls/ or you can come turn the switch on and off in person this week at the AFRU gallery’s “Byte ME 2013″ show which opens Friday (details at http://www.afrugallery.com/ai1ec_event/byte-me/?instance_id=58)

I should have some code up later this month walking through this.