Benutzer-Werkzeuge

Webseiten-Werkzeuge


project:one_button

one button

The one button project was born in yet another attempt to fix social problems through technology. Though this doesn't work most of the time - in this case it might actually work - be it only as yet another social experiment.

How everything stared

Makefu was annoyed by bad music playing in the shack's lounge one too many times and decided he had to do something about it. He came up with the idea to use a pushbutton to just delete that annoying song which is currently running.

Since The Internet was in bad shape (sadly no picture available) the red glowy button caught our eye and we decided to indoctrinate include it in the project. The Internet was a plastic box with a sirene and a red button powered by a 9v battery block. When you press the button, the sirene screams.

We came up with the idea that there needed to be pain involved in deleting music because otherwise we would end up with no music left. This is similar to the proof of work inside the bitcoin protocol (and everybody loves bitcoins). We scavenged the sirens out of the 'internet' and attached them to the Raspi, at least that was the idea. Basically you have to weigh whether the music is bad enough for you to endure the sirens.

Connect the cables

After the brain storming phase the parts only needed to be combined:

  • A raspberry Pi as the brain of the one button
  • Sirens which can be started and stopped by the one button
  • The red button to trigger the cleansing process
  • The led in the button

Wookie tried hooking up the electronics - but failed miserably - and has not been seen since. We quickly hacked some mosfets that fell out of an old motherboard (those are good sources for N-Channel hexfets) and we learned in the process how to use them - and which type goes along well with a „weak“ source like a raspberry pi pin (50mA max!). The used N-Channel Mosfets irlr7821 can be directly run by a raspberry pi pin and they can be triggered really really fast (like > 9000 times per second).

Maybe you can calculate it like this:

Qg (max) = 14nC
14nC/3.3V (pin voltage) = 4.66nF
pin current max = 50mA
dt = (4,66nF*3,3V)/50mA ergibt dt = 280nS per switch cycle
-> 560ns periode length -> 1.786Mhz max 

Since they turned out to be too loud(!) running at 12 V we reduced the voltage to 5V thus needing another light for the button - the previously pwm'ed bulb ;-) would only give a faint glow.

One Button Core Functionality

After deciding on the functionality we want to see from the button makefu started building the software. The outcome was a very basic finite state machine which with the following triggers:

  1. The Button Edges (up/down)
  2. The State timers

The problem with button edges is that there are real-world race conditions like when you push the button for a very short time only the UP flank will be visible but not the down fank, debouncing (what you want with buttons) is not very helpful in this matter… This issue has not been resolved completely, that is why some people are somewhat scared of the button utill today :)

The current state machine code currently deployed on the one button is at https://github.com/shackspace/one_button/blob/master/tmpd_init.py

PWM'ed HAL LED

We added an led and now the button radiates a nice resemblance of hal, previously this was done via a light bulb. This turned out to be much harder than thought because the led pwm frequency needs to be adjusted 10 times a second in order to make it look like a glow.

The problem here was the PWM library crashed so often it had to be de-coupled from the one button functionality in a separate service. This service will be running in an enterprise loop.

start_hal.sh:

#!/bin/sh
cd $(dirname $(readlink -f $0))
. bin/activate

while sleep 1;do
        python hal.py
        echo "!! HAL crashed, restarting"
done

The fading code hal.py is at: https://github.com/shackspace/one_button/blob/master/hal.py

Improvements over time

Do more with one button

Some time later the one button received more awesome software features: If there is no music playing a short push will start makefu's best liked radiostream. All github pull requests regarding default radiostream may be rejected, deal with it. Also, if you give it a short press while music is playing you will skip to the next song in the playlist.

This is how the state diagram of the one button currently looks like:

In short:

  • If you push the button less than 5 seconds the song currently playing will be skipped
  • If you push it longer than 5 seconds the song will be permanently deleted from the Music Library
  • Within the timeout (1 to 5 seconds) Sirens will be screaming
  • If no song was running the default stream will be played

If a song was skipped, a stream is started or a song was permanently deleted, the one button tells this the local shackspace members via Gobbelz, the text-to-speech HTTP api on the Kiosk.

Adding snickers to the one button

Parallel to the now pretty much completed Button Project, we started a new project. We named it snickers for no reason whatsoever besides needing a name.

The idea of snickers is to capture data of very cheap 433mhz movement sensors and store them in a database (graphite in our case). We needed a device which is intelligent enough to connect to the wifi and send data to a server and the one button in that shiny white box was just waiting there to be used. The button got a USB Hub and a 32u4 uC connected via USB as at that point there was no working library to connect the 433mhz receiver directly to the RaspberryPi.

The first version of the 433mhz to graphite gateway looked like this:

SNICKERS_HOST=heidi.shack:8888
PORT=/dev/ttyACM0
stty < $PORT | grep -q "9600" || stty -F $PORT sane 9600

to_graphite(){
    GRAPHITE_HOST=${GRAPHITE_HOST:-heidi.shack}
    GRAPHITE_PORT=${GRAPHITE_PORT:-2003}
    now=$(date +%s)
    echo "$1 ${2} ${3:-$now}" | nc $GRAPHITE_HOST $GRAPHITE_PORT
}
foreach_graphite(){
  id=$1
  # every received ID counts for 50 seconds
  for i in `seq 0 50`;do
    now=$(date +%s)
    to_graphite sensors.motion.id.$id 1 $((now + $i))
  done 
}
while : ;do
        cat $PORT | while read front id back;do
            [ -z "$id" ] && continue
            echo "$(date +%H:%M) $front $id $back"
            ( foreach_graphite $id) &
        done
done

The arduino code which uses RCSwitch library can be found at https://github.com/shackspace/snickers/blob/master/microcontroller/receiver/receiver.ino

One Button Mood Light and Snickers consolidation

In order to add mood-light features we added a ws2811 led stripe (with 4 leds) from another project to the one button. Initially the led stripe run by yet another arduino (pro mini without USB in that case) and a usb-serial device.

The code currently does not permit changing of a single led as we didn't had the use case yet. The one button uses these LED to tell the members if it is booted already and if the internet is working:

  1. Initial state (set by microcontroller) : RED
  2. System booted up: GREEN
  3. No Internet access : PURPLE

Later on (we needed more free USB jacks ..) this second arduino got consolidated into a single 32u4 which now runs both the LEDs and the 433mhz receiver (arduino code is here https://github.com/shackspace/snickers/blob/master/microcontroller/receiver_plus_led/receiver_plus_led.ino )

But now a very different problem approached, normally a serial port under linux can only be opened by a single process. This means, no shell script which just reads the serial port but a comple, multi-threaded program which provides an api for changing the LED color AND sending data to the snickers backend.

For this issue we used python and the Twisted Library as it provides everything we needed, even a threaded Serial Device Listener and writer.

This is the core of the code:

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        global port
        port.write(data)

class ReaderProtocol(LineReceiver):
    def lineReceived(self, line):
        send_to_graphite(line)
        
port = SerialPort(ReaderProtocol(), '/dev/ttyUSB0', reactor, baudrate=9600)

factory = protocol.ServerFactory()
factory.protocol = Echo
reactor.listenTCP(5007,factory)
reactor.run()

As you can see reactor listens at 5007 and the Echo Server is able to use the port as a global variable. This permits reading and writing for different uses and additional external output.

you can change the color like this: echo 255 0 0 | nc localhost 5007

The full code is at https://github.com/shackspace/snickers/blob/master/one_button/one_srv.py .

Temperature Logging

We bought an el-cheapo thermometer with an external 433mhz temperature sensor for the shackspace. For logging and such we wanted to retrieve the temperature data and store it into the database we had already in use for snickers. Unfortunately at this time there was no library we could just plug into an arduino and make the magic work.

We are using an RTL-SDR TV Stick and the library rtl_433 (https://github.com/merbanan/rtl_433) which does just exaclty what we want. Because nobody wanted to fiddle with the C code we just wrapped around a python parser script which took the output of the tool and parsed the temperature of our sensor (code:https://github.com/shackspace/snickers/blob/master/433mhz_temperature/parse_rtl.py ).

The cool thing: besides the temperature the sender also sending the Humdity of the room, yay :D

NFC insulter

With a spare NFC reader lying around we thought it might be cool to interact with the one button via NFC cards. We taped the USB nfc card reader under the the upper cover but until today no code has been written to implement any functionality. The idea is to recycle code from the nfc-gateway makefu built a year ago which was actually pretty straight forward by parsing the output of nfc-scan from libnfc:

#!/bin/sh
sleep 10
while sleep 1; do
  uid=$(nfc-list | grep UID | cut -d: -f 2 | sed 's/ //g')
  do_something_with_uid "$uid"
done

Conclusion and Confession

All the code and hardware is in a 'works-for-me' state and if the system ever should break down lots of it must be rewritten! This is just a fun project which grew and grew over time, it was never meant to be reproducible. It was also not made to consolidate and streamline any software or hardware and uses whatever was lying around and looked like it could be integrated without much effort. This might be one of the purest examples of the 'Manifesto of Done' in action (http://www.brepettis.com/blog/2009/3/3/the-cult-of-done-manifesto.html ) in the shackspace.

Because to be honest, besides me (makefu) nobody is really doing anything with it, be it they are scared of the sirens, do not know what it is or just do not care as it is not critical infrastructure. It looks cool with the leds glowing, though.

I will let you grow in functionality nobody really needs as long as i have the spare time to hack it together.

I love my little retard monstrosity called one button <3 .


Creds:

  • exco - everything hardware(case,leds,wiring)
  • makefu - software
  • ciko - snickers-related activities
  • wooki - failing at hardware

Author of this writeup: makefu, exco

project/one_button.txt · Zuletzt geändert: 2017-06-21 17:16 von rixx