Topic: Use the motion sensor to control your chumby

Since I just registered, first of all: Hello Everyone!
I received my Chumby a week ago and since then I trying get improve the usability and with this the WAF (wife acceptance factor) of it. smile

I found it annoying to always have to go through the control center to achieve things like changing volume or muting the sound, so I came with the following. Maybe some of you find it useful, too.

The chumby comes with this nice 3D motion sensor. Unfortunately it is "blocked" by the control panel. To workaround this I renamed the device file to /dev/real_accel and linked /dev/zero to /dev/accel, since the control panel won't work without the /dev/accel file (it hangs).

Then I wrote a small application that just dumps the acceleration data to stdout. A shell script checks the data every second or so and triggers different things according to the motions, you do with the chumby.

At the moment the following things are implemented:

- rotate clockwise -> Volume Up
- rotate counter clockwise -> Volume Down
- slight punch -> Mute/Unmute

I post the code here, since I don't know, how to upload files (is this possible at all?)

debugchumby
--------------------

#!/bin/sh
mv /dev/accel /dev/real_accel
cd /dev
ln -s zero accel

/mnt/usb/acceld.sh > /dev/null 2>&1 &

acceld.sh
--------------

#!/bin/sh

AVPRG="/mnt/usb/accelvals"
ACCEL_DEVICE="/dev/real_accel"


[ -x "${AVPRG}" ]        || { echo "[ERROR] \"accelvals\" prg. not found." ;  exit 1 ; }
[ -e "${ACCEL_DEVICE}" ] || { echo "[ERROR] Invalid acceleration device!" ; exit 1 ; }

delta_x=100
vol_steps=10

# calibration
${AVPRG} ${ACCEL_DEVICE} > /tmp/acceldata.$$
read ver ts x y z avgx avgy avgz impx impy impz imptime imphint grange < /tmp/acceldata.$$
cal_x=${x}
cal_y=${y}
cal_z=${z}

mute="$(cat /proc/chumby/audio/mixer/left-speaker/mute)"
current_volume="$(cat /proc/chumby/audio/mixer/left-speaker/volume)"

last_impact=${imptime}

echo "Calibrated! (${cal_x}, ${cal_y}, ${cal_z}, ${last_impact})"


while [ 1 ]; do
        ${AVPRG} ${ACCEL_DEVICE} > /tmp/acceldata.$$
        read ver ts x y z avgx avgy avgz impx impy impz imptime imphint grange < /tmp/acceldata.$$
        if [ "${imptime}" != "${last_impact}" ]; then
                echo -n "[IMPACT] -> "
                if [ "${mute}" = "0" ]; then
                        mute=1
                        echo "Mute"
                else
                        mute=0
                        echo "Unmute"
                fi
                echo ${mute} > /proc/chumby/audio/mixer/both-speakers/mute
                last_impact=${imptime}
        fi

        if [ "${x}" -gt "$((${cal_x} + ${delta_x}))" ]; then
                echo "[ROLL] Right"
                current_volume=$((${current_volume} + ${vol_steps}))
                if [ "${current_volume}" -gt "100" ]; then
                        current_volume=100
                fi
                echo ${current_volume} > /proc/chumby/audio/mixer/both-speakers/volume
        fi
        if [ "${x}" -lt "$((${cal_x} - ${delta_x}))" ]; then
                echo "[ROLL] Left"
                current_volume=$((${current_volume} - ${vol_steps}))
                if [ "${current_volume}" -lt "0" ]; then
                        current_volume=0
                fi
                echo ${current_volume} > /proc/chumby/audio/mixer/both-speakers/volume
        fi
        sleep 1
done

accelvals.c

----------------
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static int accel_fd;

struct accelReadData {
  unsigned int version;
  unsigned int timestamp;
  unsigned int inst[3];  // x, y, z
  unsigned int avg[3];
  unsigned int impact[3]; // values for the last impact peak acceleration
  unsigned int impactTime;
  unsigned int impactHint;
  unsigned int gRange;    // g range in milli-g's
};

int getAccelData(struct accelReadData *ac)
{
        int rc = read(accel_fd, ac, sizeof(*ac));

        if (rc != sizeof(*ac))
                return -1;

        return 0;
}

int main(int argc, char*argv[])
{
        int rc;
        struct accelReadData ac;


        if (argc != 2) {
                fprintf(stderr, "Usage: %s accel-device\n", argv[0]);
                return -1;
        }

        accel_fd = open(argv[1], O_RDONLY);
        if (accel_fd == -1) {
                perror("open");
                return -1;
        }

        rc = getAccelData(&ac);
        printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
                ac.version,
                ac.timestamp,
                ac.inst[0],
                ac.inst[1],
                ac.inst[2],
                ac.avg[0],
                ac.avg[1],
                ac.avg[2],
                ac.impact[0],
                ac.impact[1],
                ac.impact[3],
                ac.impactTime,
                ac.impactHint,
                ac.gRange);

        return 0;
}

A tar file with everything ready-to-go it available here. Just unpack to the root directory of your usb stick.

Please use at own risk. It works for me. YMMV.

Have fun,
Rolf.

Re: Use the motion sensor to control your chumby

WOW! Fantastic idea. Hopefully, I can try this out next week. Kudos to you.

Re: Use the motion sensor to control your chumby

I'm subscribing to this thread.  Great idea!  I'll try this out soon too!

Linux Guy - Occasional Chumby Hacker

Re: Use the motion sensor to control your chumby

Great job Rolf!  It works great!  I like being able to control the volume while my widgets are running so I don't have to get into the control panel to make adjustments!

Nice work!

Re: Use the motion sensor to control your chumby

So I just unpack this to the usb flash memory and this will work? What happens if I take the usb memory out, does it return to normal ? Or is this forever?

Re: Use the motion sensor to control your chumby

@djescorcik: It is not forever. If you unplug the USB device, everything returns to normal.

Re: Use the motion sensor to control your chumby

Wow! How cool! Are you looking to develop this further? Such as for switching widgets, etc? I know there's been a lot of talk about this on the boards.

Re: Use the motion sensor to control your chumby

Unfortunately I haven't found any documentation about interacting with the flashplayer / control center. Without this, I cannot really do any stuff connected with Widgets.

If I am wrong, please somebody drop me a note.

Re: Use the motion sensor to control your chumby

great utility, thanks!

I modified the script so you can smack the display on/off big_smile

10 (edited by bleomycin 2008-07-30 23:53:43)

Re: Use the motion sensor to control your chumby

schettj wrote:

great utility, thanks!

I modified the script so you can smack the display on/off big_smile

Zapp: Awesome Script! I cant believe this isnt available out of the box.

Schettj: Would you mind posting how you did this? I would love to implement it.

Re: Use the motion sensor to control your chumby

bleomycin wrote:
schettj wrote:

great utility, thanks!

I modified the script so you can smack the display on/off big_smile

Zapp: Awesome Script! I cant believe this isnt available out of the box.

Schettj: Would you mind posting how you did this? I would love to implement it.

I don't know what schettj did, but I would replace the mute instructions with reads / writes to  /psp/dimlevel
and /proc/sys/sense1/dimlevel

To kill the display, write 2 to both of these, and to turn it back on, write 0 to them.  Fun note here:  to really make the script sweet, read in the current state of the display and store it.  Then, when the Chumby is punched / etc. change the display to "off."  If you turn off the display, it will come back on to full brightness just fine (goes from 2 to 0,) but if you go from off to "dim," (2 to 1,) the display gets weird.  Solution for this is to kick the display on full bright for a brief time (500 microseconds is enough,) then drop it down to 1 = dim.  I'd sure hate to punch my Chumby at night to find out what time it is and have it hit me with a fully bright screen...

I did not know that there were commands for "both-speakers."  Provocative.  I need to read the part in the wiki about the system variables again.

Re: Use the motion sensor to control your chumby

I was thinking if you place the Chumby face down it should go into sleep mode

Re: Use the motion sensor to control your chumby

Hi zapp,

While trying to work out how to make a Chumby impact cause a change to a specific widget (a somewhat bodgy internet radio station selector/volume control), I think I uncovered a minor bug in the C code you listed. You print to stdout the following variable:

ac.impact[3]

That's from an array of only three values; I think you meant:

ac.impact[2]

The practical result is that the binary in the archive you kindly provided (thanks, by the way - very useful) prints the impact time twice, rather than the impact z value then the time.

And if anyone has experience of using the setWidget event to the control panel, and knows whether it works for local widgets (ie listed in /mnt.usb/profile.xml), that'd be helpful: I can't make it work.

Cheers,

Brett

Re: Use the motion sensor to control your chumby

After the 1.7 update, the accelvals binary doesn't appear to work; attempts to execute it yield:
--
chumby:/mnt/usb# ls -l accelvals
-rwxr-xr-x    1 root     root         9495 May 22  2008 accelvals
chumby:/mnt/usb# ./accelvals
-sh: ./accelvals: not found
--
Does it need to be recompiled for the updated software?

Brett

Re: Use the motion sensor to control your chumby

biffel wrote:

Does it need to be recompiled for the updated software?

Yes - see this thread.

Re: Use the motion sensor to control your chumby

Hi There,

If anyone is interested, I recompiled Rolf's accelvals.c with the new toolchain. I also went ahead and fixed the minor bug it had. Send me an e-mail if you are interested and I will send you the binary.

Regards,
Jose

Re: Use the motion sensor to control your chumby

Hi Josep

Have you still got the recompiled binary for this binary, would it be possible for you to send it to me?

Many thanks

Dodge

Re: Use the motion sensor to control your chumby

Can someone update the wiki with a working example?  I'd very much like to use this functionality for my wife who can't be bothered to click multiple times to get to the 2 or 3 things she wants to use the chumby for.

Re: Use the motion sensor to control your chumby

bump, still looking for a working shell script interfacing with /bin/acceld

my wife can't see very well without her glasses and the touch screen doesn't help when you can't see.  I'd like to toggle radio on/off based on impact and monitoring of /bin/acceld.  Unfortunately my shell scripting is about 8 years out of last use and my attempt to use awk to parse the output of /bin/acceld have failed.

Re: Use the motion sensor to control your chumby

Wow, great script. I would suggest that this should be included when the device is shipped so it can be used out of the box.

With regard to the bug unraveled on the C distribution source, how were the impacts accessed? Is it possible that it is caused by an null pointer to something out of bounds?