If you run lsusb
and then plug in a USB device and re-run lsusb
, do you see the new device show up in the list?
Posts made by fader
-
RE: USB Not Working
-
RE: RESOLVED: Access GPIO pins with OLED expansion
You could connect the pins that are needed for the OLED with jumper cables rather than having to plug the OLED directly into the Omega:
Basically it only needs i2c, ground, 3.3v, and 2.8v pins. (I used an old IDE ribbon cable to do this in a project where I wanted the OLED and GPIO at the same time.)
It would be great to have a small adapter or something for this though!
-
RE: Notification when the dryer finishes
My code for this is really hacky and not something I'd want to be judged on or tell other people to use But I can throw in the bulk of it as a starting point other people can use to make something better.
I wrote a shell script to install all the packages and put the scripts into /etc/rc.local (to start at boot). The "KEYPAD" listed there is the USB ID of the keypad I used, which wasn't recognized as a USB keyboard natively.
#!/bin/sh AUTOSTART="python `pwd`/run.sh" KEYPAD="hid-generic vendor=0x05a4 product=0x9759 maxSize=2048" opkg update opkg install python-light python3-light pyOnionI2C libmosquitto mosquitto-client python3-codecs # Set up the keypad grep -q "$KEYPAD" /etc/modules.d/hid-generic || sed -i \$i"$KEYPAD" /etc/modules.d/hid-generic # Cause the script to start at boot: grep -q "$AUTOSTART" /etc/rc.local || sed -i \$i"$AUTOSTART" /etc/rc.local
That will get you all the packages needed to run things as well.
The most useful part is probably the library for working with the accelerometer. There was Raspberry Pi-specific code for working with it on GitHub, which I forked and modified slightly to work with the Onion: https://github.com/mccollam/mpu6050
I built a little service to poll the sensor and make the data available over a socket, which is here:
#!/usr/bin/env python from mpu6050 import mpu6050 import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 6000)) sock.listen(5) mpu = mpu6050(0x68) # Prime readings so we have something to compare against accel = mpu.get_accel_data() temp = mpu.get_temp() while True: connection, client_address = sock.accept() try: while True: data = connection.recv(1024) if data != '': # TODO: Might eventually want to actually look at the incoming request # but for now just return everything accel = mpu.get_accel_data() temp = mpu.get_temp() # Looks like the json libs for python2 are busticated on the Onion :( result = '{ "temp": ' + str(temp) + ', "x": ' + format(accel['x'], '.12f') + ', "y": ' + format(accel['y'], '.12f') + ', "z": ' + format(accel['z'], '.12f') + '}' connection.sendall(result) else: break finally: connection.close()
(Note that I don't do a lot of error or bounds checking here, so it would be pretty easy to cause this script to crash by feeding it weird inputs over the socket it opens. So don't do that. )
I also ended up having to write my own JSON encoder as I was having issues with the built-in one on the Onion. By the time I got there I was getting a bit frustrated so I just generated it myself rather than digging into the errors too far.
Next up is the code that polls the keypad. I had written something really elegant that polled without blocking (using
select
) and was lightweight and just generally great. It worked fine on my laptop but not on the Onion, so I ended up doing a huge hack and having a separate script listen for keyboard events and write the results to a file that gets read by the main program. I'm not proud of this:import os from subprocess import call devicefile = '/dev/input/event0' scratchfile = '/tmp/notify_0' notifyfile = '/tmp/notify' # MQTT path: mqttPath = 'XXXXX/basement/dryer/' # The location of the MQTT server: mqttServer = 'mqtt.XXXXX.com' # The MQTT server port (default 1883): mqttPort = 1883 byte = [] i = open(devicefile, 'rb') notifyPerson = '' notifyMethod = '' def mqttPub(path, value): call(["mosquitto_pub", \ "-r", \ "-h", str(mqttServer), \ "-p", str(mqttPort), \ "-t", str(mqttPath) + str(path), "-m", str(value)]) while True: for bit in i.read(1): byte.append(bit) if len(byte) == 8: if byte[1] == 1 and byte[7] == 1: if byte[3] == 55: notifyPerson = 'Alpha' notifyMethod = 'email' elif byte[3] == 98: notifyPerson = 'Alpha' notifyMethod = 'sms' elif byte[3] == 73: notifyPerson = 'Bravo' notifyMethod = 'email' elif byte[3] == 72: notifyPerson = 'Bravo' notifyMethod = 'sms' elif byte[3] == 77: notifyPerson = 'Charlie' notifyMethod = 'email' elif byte[3] == 76: notifyPerson = 'Charlie' notifyMethod = 'sms' elif byte[3] == 81: notifyPerson = 'Delta' notifyMethod = 'email' elif byte[3] == 80: notifyPerson = 'Delta' notifyMethod = 'sms' elif byte[3] == 83: notifyPerson = 'Echo' notifyMethod = 'email' elif byte[3] == 82: notifyPerson = 'Echo' notifyMethod = 'sms' elif byte[3] == 28: notifyPerson = '' notifyMethod = '' o = open('/tmp/notify_0', 'w+') o.write('{"notifyPerson": "' + notifyPerson + '", "notifyMethod": "' + notifyMethod + '"}') o.close() os.rename(scratchfile, notifyfile) mqttPub('notifyPerson', notifyPerson) mqttPub('notifyMethod', notifyMethod) byte = []
The main chunk of code that pulls everything together and updates the UI is here:
#!/usr/bin/env python # This script would be way shorter and cleaner if this worked: #import mosquitto.publish as publish import time from subprocess import call import select import socket, json # Name of this sensor (the MQTT path): mqttPath = 'XXXXX/basement/dryer/' # Whether or not to attempt to use an attached OLED display: enableOLED = True # The location of the MQTT server: mqttServer = 'mqtt.XXXXX.com' # The MQTT server port (default 1883): mqttPort = 1883 # Frequency of MQTT messages (in seconds): mqttFreq = 5 # Measurement frequency (in ms): measureFreq = 100 # Absolute change of accelerometer readings to count as 'running': jitter = 0.6 # Percentage of 'running' readings to change status to 'running': runChange = .45 # Percentage of 'stopped' readings to change status to 'stopped': stoppedChange = .65 # File to find the person to notify notifyFile = '/tmp/notify' ##### def mqttPub(path, value): # If the MQTT libs worked, this would be a single line: #publish.single(mqttPath + "path", value, hostname=mqttServer, port=mqttPort) call(["mosquitto_pub", \ #"-r", \ # enable to retain old messages "-h", str(mqttServer), \ "-p", str(mqttPort), \ "-t", str(mqttPath) + str(path), "-m", str(value)]) def update_display(): if notifyPerson != "": notify = notifyPerson + " (via " + notifyMethod + ")" else: notify = "[no one]" # By getting the string written to the display to be exactly the right length, we can # update the display without clearing it first (which is slow and a bit ugly when doing # it frequently). That's the reason for assembling it as one string with a bunch of # carriage returns and blasting it to the display all at once. dtempC = "%.1f" % temp dtempF = "%.1f" % (9.0/5.0 * temp + 32) display = "XXXXX Dryer\\n\\n" \ + "Temp: " + dtempC + "'C (" + dtempF + "'F)" \ + "\\nStatus: " + status \ + "\\n\\nNotify:\\n " + notify + "\\n" call(["oled-exp", "-q", "write", display]) ##### if enableOLED: # Initialize and clear display call(["oled-exp", "-q", "-i"]) cycles = 0 running = 0 stopped = 0 lastX = 0 lastY = 0 lastZ = 0 status = "stopped" notifyPerson = "" lastNotifyPerson = "" notifyMethod = "" lastNotifyMethod = "" accel = {} sleeptime = float(measureFreq) / 1000 while True: accel['x'] = 0.0 accel['y'] = 0.0 accel['z'] = 0.0 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(('localhost', 6000)) message = 'feed me' sock.sendall(message.encode()) data = sock.recv(1024) parsed = json.loads(data.decode()) accel['x'] = parsed['x'] accel['y'] = parsed['y'] accel['z'] = parsed['z'] temp = parsed['temp'] finally: sock.close() # Measure change since last reading on each axis # (a more accurate way to do this would be to get a differential but # honestly that level of accuracy is not needed here and is more # expensive to calculate) dX = abs(accel['x'] - lastX) dY = abs(accel['y'] - lastY) dZ = abs(accel['z'] - lastZ) if dX > jitter or dY > jitter or dZ > jitter: running = running + 1 else: stopped = stopped + 1 if (cycles >= mqttFreq): if status == "stopped": if float(running) / (float(running) + float(stopped)) > runChange: status = "running" else: if float(stopped) / (float(running) + float(stopped)) > stoppedChange: status = "stopped" # FIXME: OMG THIS IS AWFUL # HUGE HACK: This should actually receive an MQTT message for updating # the person and method for notification. It doesn't currently because # of the lack of support for Python MQTT in OpenWRT :( notifyPerson = "" notifyMethod = "" o = open('/tmp/notify', 'w+') o.write('{"notifyPerson": "", "notifyMethod": ""}') o.close() #mqttPub("notifyPerson", "") #mqttPub("notifyMethod", "") mqttPub("status", status) mqttPub("temperature", temp) cycles = 0 running = 0 stopped = 0 if enableOLED: update_display() lastX = accel['x'] lastY = accel['y'] lastZ = accel['z'] f = open(notifyFile, 'r') notify = json.load(f) notifyPerson = notify['notifyPerson'] notifyMethod = notify['notifyMethod'] if notifyPerson != lastNotifyPerson: update_display() lastNotifyPerson = notifyPerson lastNotifyMethod = notifyMethod f.close() cycles = cycles + sleeptime time.sleep(sleeptime)
Finally, the shell script that runs everything is:
#/bin/sh # Yet another Onion bug, local DNS doesn't work by default :( sed -i s/127.0.0.1/10.1.10.1/ /etc/resolv.conf while true do echo '{"notifyPerson": "", "notifyMethod": ""}' > /tmp/notify python /root/dryer/sensor.py & SENSOR=$! python3 /root/dryer/keyboard.py & KEYBOARD=$! sleep 3 python3 /root/dryer/ui.py sleep 1 kill $SENSOR $KEYBOARD done
(The
kill
statement in there is just to make everything restart fresh if the mail script crashes. It was useful during debugging.)I hope this is helpful to people! Like I said, probably the only really good bit is the library for the accelerometer so hit that up on GitHub.
-
Notification when the dryer finishes
Remote Dryer Alarm
I live in a multifamily house with a washer and dryer in the basement. Which means that if you are on the third floor and want to see if your clothes are dry yet, you might have a very long hike!
So I used an Onion Omega and an accelerometer (a cheap but functional MPU-6050) to make something to help out with this:
(The accelerometer is slightly out of view, but it's attached with a magnet to the back of the dryer just below the Onion display.)
It detects when the dryer is started or stopped and sends a message to a remote system (using MQTT). It also allows people to push a button to select who should be notified and how, and displays the status and notification selection on the OLED display.
Parts I used:
- An Onion Omega (version 1)
- An Onion dock (to provide power and make it easier to break out the GPIO pins)
- An Onion display
- A USB number pad keyboard
- A USB hub (to make the keypad show up properly)
- A 40-pin ribbon cable (to hook up the display)
- Wire, proto boards, etc.
How it works:
There are three Python scripts running on boot. (See below for why I ended up with three.)
- A sensor script - polls the MPU-6050 for acceleration on each axis every 200ms
- An input script - polls the keyboard (directly accessing /dev/input) and translates keycodes into who to notify and how
- A main script that picks up the values from the other two, updates the display, and sends out MQTT messages
The actual notification is running on a separate system which receives the MQTT messages and acts on them. (I use Amazon SNS to do the actual notifications as the free tier allows 100 SMS or many thousand emails per month and we just don't do that much laundry.)
What went well:
Initially I wrote everything in one single script, and it was really quite easy to get the data from the accelerometer using the Omega I2C Python libraries and write everything to the display.
Sadly, that's about where the 'easy' parts ended.
What went poorly:
Lots of things combined to make this project way harder than it should have been.
One weird one is that the USB keypad wouldn't show up in /dev/input unless I connected it through a USB hub. That doesn't make a ton of sense to me but I had a hub lying around so I didn't investigate much beyond that, but it did cost me a couple of hours of head-scratching.
The biggest pain is that the packages for the Omega are all over the place. There seems to be a bug in the Python2 packages that provide
select()
, meaning I couldn't poll the keypad properly from my script. Quick tests showed that Python3 worked properly, but there just aren't Onion I2C libraries for Python3. I ended up having to split my simple script in two and run one in Python2 (for the accelerometer) and one in Python3 (for the keypad) and pass data between them with a socket. This dramatically increased the complexity of the project.Similarly, the MQTT packages for the Omega don't have Python support. So the code I developed on my laptop didn't work. This is why I ended up with a third script: I had to have something sending/receiving MQTT using the command-line tools rather than doing it inside my scripts. Again, this was a big increase in complexity.
Finally, the 2.0mm pin pitch on the Onion means I couldn't use standard 2.54mm breadboards or proto boards to build my project. I wanted to have everything on one board but it would cost more to buy a
My feelings at the end:
I learned a ton about I2C here (as it was something I really hadn't done before) and up until running into Python2 bugs, this was pretty easy to do. But unfortunately it repeats a pattern I keep running into: the packages I want to use on the Omega are frequently broken. Usually it's that they simply won't install due to kernel header differences but this time it was missing a lot of support I needed (MQTT python bindings, Python3 bindings for the Onion I2C libraries). I'll probably stick with using the Omega for very simple projects where I'm not interfacing with anything more complex than a webserver or a single USB device.
I really hope some of the package issues are resolved (especially the kernel header mismatches as that should just be a matter of throwing some compilers at the repository and waiting) -- I want to use the Omega for many more things but it's just a little too painful right now. I'll check in after the version 2 shipping wraps up and see how things are going then.
-
RE: pyOnionI2C for python3
Yeah, that is my next step (actually probably running them both and using a socket to pass data between them). It would be way simpler and cleaner for me to be able to do this in one script, but that is at least a fallback plan.
-
pyOnionI2C for python3
Is there a way to get the i2c python libraries for python3? I have a project that needs some python3 features but I only see the python2 Omega i2c libraries.
-
RE: USB keypad not showing up in /dev/input
Thanks for the pointer! I think there is more going on here though -- after I plugged in a USB hub to be able to test this device and use another USB device at the same time, it magically showed up in /dev/input. No idea why as the hub isn't powered or anything... but at least it's working now. I'll just tuck the hub in with my project.
-
USB keypad not showing up in /dev/input
So this is a weird one: I've got a USB numeric keypad that does not seem to create an entry in /dev/input when connected. It shows up on lsusb but that's about it.
Other USB keyboards properly create an entry in /dev/input, so that subsystem is working. And the keypad shows up in /dev/input and works just fine there on my Ubuntu machine (where dmesg tells me it's using
hid-generic
), so I know it is working as well.Any clue what would cause this? I'd love to use this keypad as the input device for a project I'm working on.
-
RE: Shape Onion's future! We want your feedback!
Yeah, same here. I did it on my phone and when I hit the 'next' arrow on the last question, I just got redirected to store.onion.io. If that's expected behavior then I'll assume it worked correctly
-
Using the Omega as a wireless to ethernet bridge
There's a wiki page outlining how to make the Omega into a wifi access point, sharing ethernet wirelessly. Is it possible to do this the other direction, connecting an ethernet device to a wireless network?
-
RE: Remote serial control of a projector
I posted a bit more detail about the system and how I built everything over at my blog. It's not a full blueprint for what I built but gives a few small samples of code and the overall architecture. I'm happy to answer questions or go into more detail if anyone is interested!
-
RE: Connect OLED with only necessary pins
There was a diagram in a post earlier about this: https://community.onion.io/topic/260/pinouts-for-omega-docks-and-expansions/3
I don't know off the top of my head what each of the pins carries but it should be possible to figure that out based on the pinout diagram on the Omega.
-
RE: resolvfile option in /etc/config/dhcp being ignored?
@Boken-Lin Yeah, what I'd ideally like is for the Omega to pick up my router as the primary DNS server. Since the router automatically adds an entry for anything it gives a DHCP address to, it saves me from ever having to go back and touch /etc/hosts on devices when I add something new to my network.
What confuses me is that the config files are getting properly written, but they don't seem to be used. If I just copy over the (auto-generated) /tmp/resolv.conf.auto to /tmp/resolv.conf, it picks up DNS from my router just fine. And per the openwrt docs, the (auto-generated) entry for /tmp/resolv.conf.auto should be added along with /tmp/resolv.conf by the settings that are already in /etc/config/dhcp.
So I'm pretty sure there's a bug somewhere, whether it's openwrt or the generated config (or somewhere else) but I'm just not sure where to dig past this.
-
RE: Remote serial control of a projector
Yeah, @Boken-Lin there are definitely some more advanced uses I could put this to. I've actually built out a nice remote control interface that works with not only the projector but with my stereo receiver and the Philips Hue lights I have in that room -- one button to dim the lights, turn on the projector, and set up the audio.
If I can ever get out from under the mountain of work I've got at my paying gig I'll write up more details about it and maybe try to do a tutorial for others interested in something similar. Thanks for the ping here to remind me to work on that some more!
-
RE: Issue with Cloning a Git Repository
I had this issue as well. You need to 'opkg install git-http' to provide the http/https support package for git.
-
RE: Where to store program files?
It's probably easiest to just copy your program to /root and run it from there. You shouldn't need to worry much about putting it into the system-wide location for programs or building your own package or anything. You will need to specify the path when you run it though -- you'll say "/root/helloWorld.py" (or you can use "./helloWorld.py" if you are currently in /root). You also have to mark it as an executable file before you can run it, e.g. "chmod +x helloWorld.py". (chmod is 'change mode', +x means add execute mode.)
To get your file onto the Omega you should be able to use scp. If your host is Linux or OSX you can just say "scp helloWorld.py root@[onion IP address]:/root/" to copy it there. For Windows I'm not sure but I believe WinSCP is something I've heard of people using.
Finally, you're right about opkg handling the install path for you. If you do "opkg install python-light" it will put all the python bits in the right place with no extra work from you -- just type "python" after the install and it will Just Work
-
RE: resolvfile option in /etc/config/dhcp being ignored?
Further info/examples:
root@myonion:/etc/config# cat /tmp/resolv.conf search lan nameserver 127.0.0.1 root@myonion:/etc/config# cat /tmp/resolv.conf.auto # Interface wwan nameserver 10.1.10.1 search mydomain root@myonion:/etc/config# ping -c 1 google.com PING google.com (146.115.8.113): 56 data bytes 64 bytes from 146.115.8.113: seq=0 ttl=61 time=76.807 ms --- google.com ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 76.807/76.807/76.807 ms root@myonion:/etc/config# ping -c 1 goodaddress.mydomain ping: bad address 'goodaddress.mydomain' root@projector:/etc/config# cp /tmp/resolv.conf.auto /tmp/resolv.conf root@myonion:/etc/config# ping -c 1 goodaddress.mydomain PING goodaddress.mydomain (10.0.0.135): 56 data bytes 64 bytes from 10.0.0.135: seq=0 ttl=64 time=5.364 ms --- goodaddress.mydomain ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 5.364/5.364/5.364 ms root@myonion:/etc/config# grep resolvfile dhcp option resolvfile '/tmp/resolv.conf.auto'
-
resolvfile option in /etc/config/dhcp being ignored?
I'm having some trouble resolving local addresses and wondering if I'm missing something.
I can resolve things from external DNS just fine, so I know it's not a general resolver issue, but I can't resolve anything on my local network from the Omega. I see that the proper settings are getting picked up via DHCP and written to /tmp/resolv.conf.auto. And in fact, if I copy those settings into /tmp/resolv.conf, everything resolves.
Looking at the openwrt docs it seems like this should work, as long as the proper resolvfile is set in /etc/config/dhcp. I checked and it's set up right, but doesn't seem to be taking effect.
Anybody know how to get local DNS to work without tweaking /tmp/resolv.conf manually?
-
Cheap, easy case for Omega and mini dock
(I've been gone for a bit due to nonstop work travel but hopefully I'll be back for a while and able to play with the Omega again!)
A few weeks ago I was working on a remote control for my video projector. When I finally got around to mounting the projector on the ceiling, I realized I didn't want the Omega just exposed on the end of a wire. Unfortunately, nice small project cases can cost about as much as the Omega itself!
But fortunately for me, I eat a lot of mints. ("Live fast, die young, leave a minty fresh corpse" is my motto!) And I had a ton of Altoids tins lying around, which got me wondering.
Could it possibly fit?Lo and behold, it fits wonderfully!
A new home for an Omega!I spent a few minutes digging through the basement to find my tin snips and attacked the tin.
A bit blurry but it's hard to balance a camera and an implement of destruction simultaneously.A few minutes later... success!
Snug as an onion in a tin, as they say.My two worries were that I'd short something due to the exposed solder and traces on the Omega and that I'd built a Faraday cage and would block all WiFi. The first bit was easy: I cut a business card up. Two thirds (folded) went on the bottom, one third on the top.
A bit sloppy but nobody will see this part.And for WiFi I just closed the lid and tested. And it worked! I lose about 10dBm with the lid closed vs. open, but for my purposes as long as I can send a few bytes to my 3-line PHP webservice I'm all set. Speed really isn't an issue.
If anyone is really interested in duplicating this, I could probably measure where I put the holes. But really it wasn't difficult to eyeball -- I put the Omega in the tin, put some pencil marks where I thought the USB cables would go, and trimmed until it fit. One thing to note is that I had to cut pretty far down to get everything to work when the lid was closed. And I had to nip just a touch out of the lid on the microUSB side as the cable was just a mm or so too high.
Watch those edges! I should really cover them with tape or something.But overall this worked better than I'd hoped. The only thing left to do is paint it black to match the projector and I have a perfect unobtrusive web control for my projector!
Sweet, sugar-free Onion! -
RE: Using a USB sound card
@Rudy-Trujillo those bits from /proc/asound show that you have a recognized USB sound device, but that the device isn't providing much more than a raw ID string back. Instead of providing a human-readable set of information, it's giving its ID number ("U0x46d0x8dd") and nothing else. (The "usb-ehci-platform-1.4, full speed" part is just saying what USB chipset and USB revision are being used, neither of which are really important for this purpose.)
That said, you should still have access to some nice ALSA (the Advanced Linux Sound Architecture) utilities. I'm traveling and don't have an Omega with me to give the exact commands, but take a look here: http://www.tldp.org/HOWTO/Alsa-sound-6.html This should give you at least a starting point to dig into what ALSA provides