3D printed Stevenson screen
@Dimitrios commented the other day on my Funky+DHT22 post that my readings seem to have a lot of 99.9% relative humidity readouts and suggested that it may be due to the black box that I enclosed the project. I do have some holes drilled, but probably not enough to get decent air circulation:
I compared my readings to Weather Underground data that I also collect and they seem to be relatively close, yet don’t hit the 99.9% RH mark that often:
Dimitrios suggested to send me a 3D-printed Stevenson screen to try out (Thanks!). I got it today, quickly inserted the Funky+DHT22+AAA battery, and in the process took a battery measurement. It measures 1.35V, pretty amazing since I inserted that battery on Sept. 15th 2012. It will work down to 0.8V, so I guess it will be around for a year at least. Some pictures of the setup:
The screen was printed in natural PLA and then painted white to increase reflectivity.
One of the M3 support screws is cut longer, to serve as the RFM12B
antenna for the 868MHz band.
Pretty cool
Thanks again, Dimitrios!
p.s. freeCAD design files for the screen are available: stevenson_screen_v2 (86)
Power consumption puzzle
Recently I had to go abroad for a few days, and given a new access path I just added to my HouseMon setup, it let me track things while away from home. Is that good? Eh, sort of…
The nice thing is that I can now check the solar production in the evening while away from home. And obviously I can then also check on the energy consumption – here’s what I saw:
Very odd. Something was turning on and off all the time! Here’s a close-up:
As you can see, I did figure it out in the end – but only after this had been going on for two days, on the phone with Liesbeth to try and identify the source of this behaviour.
It was a bit worrying – that’s a 300..400 watt power draw, every 45 seconds. Going on for days. This is enough energy to cause serious heat problems and my worry was that it was some sort of serious malfunction, with a thermal safety constantly kicking in.
Yikes. Especially when you’re away, knowing there is no one at home during the day…
The answer to this riddle isn’t 100% conclusive, because I did find a way to stop the pulsing, but turning power on again did not cause the pulsing to resume:
This is crazy. The only explanation I found, was the laser printer: I had printed a few pages before going away (and as far as I can remember, I did turn the printer off after use). The printer was behaving erratically, and I had to turn it on and off a few times.
So my conclusion is: the laser printer (which has a toner heater built-in that can indeed easily draw a few hundred watts) got stuck in some weird mode. And kept me worried for a few days – all just because of me being a geek and checking my graphs!
I don’t know what lesson to take home from all this: stop monitoring? stop checking? stop traveling? – or perhaps just stop worrying when there’s nothing you can do about it ;)
Oscilloscope sampling rate
Just to finish the series on Raspberry Pi I/O – here’s proof of its GPIO pulsing speed:
The trouble is the irregularity caused by Linux’s multi-tasking properties, and I wanted to show you some examples of that. After a few dozen captures, I came up with this one:
Looks pretty bad, right? Tons of hickups in what was meant to be a 5.2 MHz pulse train.
Not so fast…
The sample rate used by the oscilloscope for this capture was 10 MHz, so it’s sampling the signal at 100 ns intervals. That’s extremely risky, because when the signal is also pulsing at this rate, you might end up missing each peak for a substantial amount of time. This would make it appear as if the signal was low or high all the time, despite its rapid changes.
This effect is called “aliasing”, and the solution is simple:
Do Not Sample At A Rate Close To The Frequencies In Your Signal!
I’m inclined to discard the above snapshot – it’s probably a measurement artefact.
Here’s another screen, this time at 50 MHz sample rate, i.e. 20 ns between captures:
At that rate, it’s impossible to miss pulses which are all in the range of 100 ns or longer. As you can see, there are still glitches (almost on every snapshot there is one), but it’s not as bad as the previous screen shot was suggesting.
Anyway. Enjoy your RPi and all the Linux high-level stuff it can do (like, ehm, run the Arduino IDE and cross-compile stuff for ATmega’s), but beware of treating it like a CPU which is exclusively at your service.
A Raspberry Pi is fast most of the time, but it’s (occasionally) a bit occupied with itself…
Fast I/O on a Raspberry Pi
To follow up on yesterday’s post about WiringPi and how it was used to display an image on a colour LCD screen attached to the RPi via its GPIO pins.
A quick calculation indicated that the WiringPi library is able to toggle the GPIO pins millions of times per second. Now this might not seem so special if you are used to an ATmega328 on a JeeNode or other Arduino-like board, but actually it is…
Keep in mind that the RPi code is running under Linux, a multi-tasking 32-bit operating system which not only does all sorts of things at (nearly) the same time, but which also has very solid memory and application protection mechanisms in place:
- each application runs in its own address space
- the time each application runs is controlled by Linux, not the app itself
- applications can crash, but they cannot cause the entire system to crash
- dozens, hundreds, even thousands of applications can run next to each other
- when memory is low, Linux can swap some parts to disk (not recommended with SD’s)
So while the LCD code works well, and much faster than one might expect for all the GPIO toggling it’s doing, this isn’t such a trivial outcome. The simplest way to deal with the RPi’s GPIO pins, is to manipulate the files and directories under the /sys/class/gpio/ “device tree”. This is incredibly useful because you can even manipulate it via plain shell script, using nothing but the “echo”, “cat”, and “ls” commands. Part of the convenience is the fact that these manipulations can take place entirely in ASCII, e.g. writing the string “1″ or “0″ to set/reset GPIO pins.
But the convenience of the /sys/class/gpio/ virtual file system access comes at a price: it’s not very fast. There is too much involved to deal with individual GPIO pins as files!
WiringPi uses a different approach, called “memory mapped files”.
Is it fast? You bet. I timed the processing time of this snippet of C code:
int i; for (i = 0; i < 100000000; ++i) { digitalWrite(1, 1); digitalWrite(1, 0); } return 0;Here’s the result:
real 0m19.592s user 0m19.490s sys 0m0.030sThat’s over 5 million pulses (two toggles) per second.
This magic is possible because the I/O address space (which is normally completely inaccessible to user programs) has been mapped into a section of the user program address space. This means that there is no operating system call overhead involved in toggling I/O bits. The mapping is probably virtualised, i.e. the kernel will kick in on each access, but this is an interrupt straight into protected kernel code, so overhead is minimal.
How minimal? Well, it takes less than 90 ns per call to digitalWrite(), so even when running at the RPi’s maximum 1 GHz rate, that’s less than 90 machine cycles.
Note how the RPi can almost toggle an I/O pin as fast as an ATmega running at 16 MHz. But the devil is in the details: “can” is the keyword here. Being a multi-tasking operating system, there is no guarantee whatsoever that the GPIO pin will always toggle at this rate. You may see occasional hick-ups in the order of milliseconds, in fact.
Is the RPi fast? Definitely! Is it guaranteed to be fast at all times? Nope!
What it took to generate that LCD image
As shown yesterday, it’s relatively easy to get a bitmap onto an LCD screen connected to a few I/O pins of the Raspberry Pi.
But there were some gotcha’s:
- the image I wanted to use was 640×480, but the LCD is only 320×240 pixels
- the WiringPi library has code to put a bitmap on the screen, but not JPEGs
- this is easy to fix using the ImageMagick “convert” command
- but the result has 24-bit colour depth, whereas the LCD wants 16-bit (5-6-5)
The “convert” command makes things very easy, but first I had to install ImageMagick:
sudo apt-get install ImageMagickThen we can run “convert” from the command-line (long live the Unix toolkit approach!):
convert snap.jpg -geometry 320x240 -normalize snap.rgbThis handles both the rescaling and the transformation to a file with (R,G,B) types, each colour is one byte. As expected, the resulting image file is 320 x 240 x 3 = 230,400 bytes.
I didn’t see a quick way to convert the format to the desired 5-6-5-bit coding needed for the LCD, and since the code to write to the LCD is written in C anyway (to link to WiringPi), I ended up doing it all in a straightforward loop:
#define PIXELS (320*240) uint8_t rgbIn24 [PIXELS][3]; unsigned rgbOut15 [PIXELS]; [...] for (x = 0; x < PIXELS; ++x) { uint8_t r = rgbIn24[x][0] >> 3; uint8_t g = rgbIn24[x][1] >> 2; uint8_t b = rgbIn24[x][2] >> 3; rgbOut15[x] = (r << 11) | (g << 5) | b; }Note that this is a C program compiled and running under Linux on the RPi, and that it can therefore easily allocate some huge arrays. This isn’t some tiny embedded 8-bit µC with a few kilobytes – it’s a full-blown O/S running on a 32-bit CPU with virtual memory!
The other gotcha was that the bitmap to be supplied to the LCD library on top of WiringPi was expected to store each pixel in a 32-bit int. Total waste of space, and probably the result of a rushed port from the UTFT code (written to assume 16-bit ints) to the RPi. Which is why rgbOut15 is declared as “unsigned” (int, i.e. uint32_t) array, although the image really only needs an uint16_t. Oh well, what’s an extra 150 kB, eh?
Anyway, it works. Perfection can wait.
Note that this sends out all the data pixel by pixel to the display, and that each pixel takes the bit-banging of 2 bytes (the interface to the LCD is 8-bit wide), so each pixel takes at least 20 calls to digitalWrite(): 8 to set the data bits, and 2 two to toggle a clock pin – times two for the 2 bytes per pixel. That’s at least 4.6 million GPIO pin settings in half a second!
Tomorrow, I’ll show how WiringPi can make GPIO pins change in under 100 nanoseconds.
Getting an image on the LCD
To follow up on yesterday’s setup, I’ve managed to drive the display from Linux, using the WiringPi library by Gordon Henderson.
It supports driving the Raspberry Pi’s GPIO pins from C using Arduino- / Wiring-like calls to digitalWrite(). That, in combination with the UTFT library by Henning Karlsen, and some work done by iTead to combine everything was enough to get this self-portrait:
The display is a bit shiny, and the contrast and brightness are a bit low, unfortunately :(
Drawing the image takes about half a second, but considering that it’s all done through bit-banging of a few I/O pins from a “user space” program, that’s pretty good actually!
There are a couple of interesting (and sneaky) details, which I’ll go into in the next post.
Hurray for open source and the remixing / sharing it enables!
LCD screen for the RPi
For a little side-project I’m involved in (more on that in a future post), I wanted to try adding a little LCD screen with touch sensor to a Linux setup. Found this one at iTead:
There’s a little ribbon cable and adapter (just re-wiring) available for it, which allows plugging this thing into a Raspberry Pi. The nice thing about this screen, apart from being 320×240 pixels and 16-bit color TFT, is its physical size – just right for a stacked setup:
Stay tuned, as I explore how to hook this thing up and make it show stuff…
Texas Instruments SimpleLink CC3000 WiFi Module
There is a relatively new product by Texas Instruments – the SimpleLink CC3000 WiFi module that is quite small and cheap – $12. Looks quite promising, size is about as much as a fingernail:
There is a KickStarter project using that chip already, quite intriguing. There is still no library for Arduino, but I guess it is just matter of time before one appears. There is an initiative here.
Other projects (in progress) that use that chip are the WiFiduino
..and a CC3000 shield project:
I will keep an eye on these projects, WiFi is something I long wanted to include in my projects.
(223)
Accurate timing with jittery packets
A few days back I mentioned the SYNC message mechanism in CANopen, and how it can have about 150 µs jitter when sent out on a CAN bus running at 1 Mbit/s.
Here’s the basic idea of sending out SYNC packets at a pre-defined fixed rate:
Once you have such a mechanism, you can do things like send out commands which all devices need to perform on the next sync for example. Nice for controlling the X, Y, and Z axis of of a CNC machine with the accuracy needed to make them all move exactly in sync.
The SYNC message has a very very high priority on the CAN bus, but even so, it can be delayed if it wants to send while some other transmission is taking place. So even though it will probably be first one to go out, it still has to wait for the bus to become available:
As a result, that SYNC pulse we wanted to arrive on time T ended up coming in at T + X. With X being under 200 µs when the bus is running at 1 MHz, but still.
Can we do better?
Yes, and no. We can’t avoid the jitter in that SYNC packet. But while the master sending out that SYNC packet cannot time it more precisely, it does know when the packet actually went out. So it does in fact know what T + X ended up being for that transmission.
And here’s the clever bit: the master can now send out a second (slightly lower priority) packet with a time stamp in it, i.e. containing that “T + X” value, down to the microsecond in fact. The arrival time of that time stamp packet is not so important. What matters is that each slave tracks exactly when the sync came in, and then uses the time stamp to adjust for any difference or drift that may be taking place.
This won’t help make the SYNC pulses come in more accurately, but it will let each slave know exactly what the time of that pulse was, and hence how accurately their own clocks are running. With this mechanism, all clocks can safely be assumed to run within 1..2 µs of each other, and therefore all future commands can now be tied to specific times which are known to be matched up between all slaves with two orders of magnitude better accuracy.
Ingenious, that CAN bus, eh?
Cheap DIY power monitor
My father asked me to create a standalone power monitor for him, he’d like attach it to some appliance and see its momentary and accumulated over time power consumption. Using OpenEnergyMonitor’s resources that was an easy task to do. I used a SCT-013-000 current transformer to sense the current and a 9V transformer to sense the voltage:
I used one of the 1.8″ TFTs that I have toyed with earlier as a status display. The computing power comes from my el-cheapo Arduino compatible on veroboard that I described here. The whole thing is quite bulky because of the transformers, but would fit nicely in a project box:
#define cs 6 #define dc 10 #define rst 8 // you can also connect this to the Arduino reset #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #include #include "EmonLib.h" // Include Emon Library EnergyMonitor emon1; // Create an instance float accpower=0; unsigned long lastmillis; Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); void setup(void) { Serial.begin(9600); tft.initR(INITR_REDTAB); // initialize a ST7735R chip, red tab tft.setTextWrap(false); tft.fillScreen(ST7735_WHITE); tft.setCursor(0, 0); tft.setTextColor(ST7735_BLACK); tft.setRotation(3); tft.setTextSize(1); tft.println("Starting up system.."); tft.println("http://harizanov.com"); // emon1.voltage(2, 234.26, 1.7); // Voltage: input pin, calibration, phase_shift emon1.voltage(2, 224.26, 1.7); // Voltage: input pin, calibration, phase_shift emon1.current(1, 111.1); // Current: input pin, calibration. for(int i=0; i<10; i++) { emon1.calcVI(20,2000); } tft.fillScreen(ST7735_WHITE); tft.setCursor(0, 0); tft.setTextColor(ST7735_BLACK); tft.setTextSize(2); tft.println("Accum: "); tft.setTextSize(1); tft.println("Voltage: "); tft.println("Current: "); tft.println("P.F.: "); lastmillis=millis(); } void loop() { // emon1.serialprint(); // Print out all variables (realpower, apparent power, Vrms, Irms, power factor) float realPower = emon1.realPower; //extract Real Power into variable float apparentPower = emon1.apparentPower; //extract Apparent Power into variable float powerFactor = emon1.powerFactor; //extract Power Factor into Variable float supplyVoltage = emon1.Vrms; //extract Vrms into Variable float Irms = emon1.Irms; //extract Irms into Variable tft.fillRect(70, 0 , 128, 160, ST7735_WHITE); tft.setTextColor(ST7735_BLACK); tft.setCursor(70, 0); tft.setTextSize(2); tft.print(accpower,2); tft.print("kWh"); tft.setTextSize(1); tft.setCursor(70, 16); tft.print(supplyVoltage,0); tft.setCursor(70, 24); tft.print(Irms); tft.setCursor(70, 32); tft.print(powerFactor); tft.fillRect(0, 60 , 128, 160, ST7735_WHITE); tft.setCursor(0, 60); tft.setTextSize(4); tft.setTextColor(ST7735_BLUE); tft.print(realPower,0); tft.print("W"); emon1.calcVI(20,2000); // Calculate all. No.of half wavelengths (crossings), time-out accpower += (((millis()-lastmillis) * emon1.realPower) / 3600000000); lastmillis=millis(); delay(2000); }
(291)
Another new kid on the block
Besides the Odroid U2 quad-core Linux board mentioned a few days ago, there’s another option in the same price range as the Raspberry Pi – the Beaglebone Black, a.k.a. “BBB”:
Yeah, ok, it’s slightly more expensive, but it comes with 2 GB of speedy eMMC memory built-in, whereas you need to add an SD card to make the RPi start up.
This is a bigger deal than you might think, because the BBB comes with Angström Linux pre-installed, and you can get going by simply plugging the BBB into a USB port:
- the moment you do, a memory disk appears, and it gets auto-mounted
- there’s a “start.htm” file you can double-click to launch your web browser
- then just follow instructions and you’ll be up and running
This is very similar to the way the MBED ARM module works, and it shows that streamlining the first encounter really can help people to get started – fast!
From a general point of view, the Beaglebone black is actually quite different from the RPi, despite their obvious similarities of both being low-cost, low-power, yet fairly performant little Linux stand-alone boards with with keyboard-monitor-and-mouse capability and built-in Ethernet. Here’s where they differ, at least as I see it:
The RPi is aimed at the educational market, i.e. for learning about Linux and doing cool stuff with it once you’ve mastered that first step. Get a board, hook into a huge community, get your hands dirty, and start learning and hacking!
The BBB is aimed more at the embedded Linux market, i.e. for building all sorts of advanced projects with Linux and a powerful computing platform inside. Plug it in, put your Linux and physical computing skills to work, and make neat things happen!
The difference? The RPi is the most affordable solution out there, and does really well at being a complete Linux system with fairly good video and audio capabilities, but somewhat limited I/O expandability (even just thinking about how to hook up and size an expansion board on top is a puzzle). The BBB is packed with faster and more powerful hardware (but less focused on video and audio) and is loaded with expansion connectors and pins, ready to add a board, or even a whole stack of them. Even without boards on top (called capes), you have tons of I/O pins to play with – whether you need digital, analog, PWM, or all sorts of bussed interfaces, it’s often all there.
Some details about the BBB running at 300 MHz idle (it scales to 1000 MHz on demand):
# cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 2 (v7l) BogoMIPS : 297.40 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc08 CPU revision : 2 Hardware : Generic AM33XX (Flattened Device Tree) Revision : 0000 Serial : 0000000000000000For a nice 20-min story about a project where RPi’s and BBB’s were used, see this video.
There’s a project called BoneScript, which aims to make the Beaglebone’s I/O capabilities as easy to use from JavaScript (i.e. Node.js) as what the Arduino IDE did for C/C++ and the ATmega’s I/O pins. Sounds like an excellent step in the right direction to me.
Either way, I see a bright future ahead for Node.js running on these little boards!
What’s inside that chip?
Came across an interesting post the other day, from a Russian site which looks “under the hood” of some sophisticated chips – some well-known in the West, some less so.
First, the technique of using sulfuric and nitric acid is described and illustrated:
But the really bit interesting bit is what comes out. Here’s the ATmega8:
(both pictures were copied from that site, i.e. zeptobars.ru – I hope that’s ok)
The size of this chip is 2855 x 2795 µm, i.e less than 3 x 3 mm.
Fascinating! I wonder what all the different bits and pieces are…
Trying out CANopen
Time for some electronics doodling… here are two LPCxpresso boards, with LPC11C24 ARM chips on each. One of them has been cut in half and hacked, as you can see:
The reason for using this chip is that they have CANopen drivers built into them, in ROM. That makes it a lot easier to get started, with so many things being unclear anyway – from the compiler toolchain (I ended up with a mix of ARM’s Linaro toolchain and NXP’s LPCxpresso IDE), to figuring out how to get a basic CAN packet on the bus and off again.
Anyway, couple of days of hardware + firmware tinkering, and here’s the result:
I’m getting a lot of mileage out of the Hameg HMO2024 scope as you can see, including its hardware CAN bus decoding (a paid option, but free at the time I got the intro bundle).
You’re looking at 4 packets, i.e. 2 request/response pairs going over the bus.
Note how the voltages are jumping up and down a bit. For CAN, this is irrelevant, because it works based on the difference between the CAN-L and CAN-H levels. It’s caused by the master node running its CAN interface at a slightly lower voltage (USB + diode drop). Then again, it’s rather useful for debugging because you can see who sends what! As is clearly visible above, the ACK bit comes from the other node in each exchange.
In terms of speed, there’s one packet every 145 µs, which translates to 55 Kbyte/sec for the 8-byte payload, i.e. 440 Kbit/s out of 1000 Kbit/s actual throughput (more, since there is also an address, the ACK bit, etc). It might not seem like much, but keep in mind that this is also the worst-case timing. The CAN bus does not start thrashing or losing packets when pushed to its limit – all that can happen on a maximally loaded-bus is that the lowest-priority messages will hardly ever get a chance to pass through.
On the software side, a CAN bus is really quite simple to use, since the built-in hardware does all the hard work of acquiring and releasing the bus, resending on packet damage (a noise spike, for example), adding and checking CRCs, buffering a few incoming packets, and even filtered reception – so that only specific ranges of message IDs get picked up.
Not much of this is available for Atmel chips, alas. And that ARM world sure is a lot less physical computing friendly w.r.t. open-source and platform-agnostic toolchains.
All those ARM Cortex chip manufacturers still seem to be living in the dark ages…
CANopen sits on top of CAN
The CANopen protocol sits on top of the low-level CAN bus protocol. Due to the way CAN bus packets are tagged with a message ID, but not specifically routed from or to a specific device (i.e. node), and due to the maximum packet payload size of 8 bytes, you really need something like CANopen to make it usable. For reference, here’s a 2-node CAN bus setup:
The interesting bit about CANopen, is that it’s all about data acquisition and process control (that’s what you do when you put this stuff in a car, after all). And what intrigues me about that, is the similarity with monitoring and controlling stuff around the house.
I’ve been reading myself silly lately, to wrap my head around all the CANopen terminology and to try and distill the essence of… ehm, CANopen, life, and a few other things :)
But instead of just describing CANopen as it is, and pouring lots of its concepts and new terminology on you, let me try to describe this from an outsider’s perspective:
CANopen works in terms of accessing and saving objects. It’s not necessarily 100% centralised, but that’s how it often gets used: a central CANopen node to control, inquire, and manage a bunch of CANopen slave nodes, all on the same CAN bus.
There are a lot of conventions w.r.t. these objects, because the goal of CANopen is to allow devices from different manufacturers to inter-operate (that’s probably why it’s called “open”). So there’s a standard way to find out which devices are present and what their basic capabilties are, to enable/disable each one of them, to configure their communication settings, to start and stop data acquisition streams – all with lots of room for manufacturer- and device-specific details to be managed as well.
The central concept here is the “Object Dictionary” in each device, which is indexed by a 16-bit number, plus a numeric 8-bit subindex for entries which are more structured. Objects can be 1..4 bytes, in which case they can be exchanged in one packet, or larger, in which case CANopen takes care of all the packing and unpacking.
There is a simple yet effective heartbeat mechanism, so that each device (and of course also the master) can figure out which devices are currently present, which are active, and – with timeouts – which devices seem to have dropped out for some reason.
Each device announces itself when powering up, so auto-discovery is possible, even for devices which the master has never seen before – although it’ll be more effective when the master has a detailed description of each type of device, so that it can optimally manage and control it.
There are mechanisms for urgent error reporting, dropping out gracefully, and throttling to avoid bus congestion.
Everything is prioritised (the CAN bus does that), with top priority (msg ID 000) given to essential (but infrequent) master messages, such as starting and stopping device activity on the bus. Note that, due to the top priority, these will always get through.
Next in priority is a time synchronisation message, which can be used to make all device clocks “sing in sync”. With a 1 Mbit/s bus rate, these sync messages will never have more than about 150 µs jitter (and there’s a clever optional scheme to increase the time resolution in all slaves to 1 µs).
There is much more which I can’t all describe in this post, but the one design idea I’d like to highlight is the distinction between managing a large set of objects (via SDO’s, i.e. Service Data Objects) and maximally efficient data streams (via PDO’s, i.e. Process Data Objects). Where PDO’s can be set up to be sent across in a regular time-synchronised manner or in a more ad-hoc / event-based / asynchronous fashion.
I really like this distinction: there is a large heterogenous mix of data objects, which can be accessed and changed via individual SDO requests, and there are streams of PDO data which don’t waste time and bandwidth on describing themselves – just the raw bytes. The heterogenous data objects can fully describe those streams, their exact byte (even bit) structure, the conditions under which data gets sent, their frequency, and their priority.
Lots of interesting connections with the way the RF12 driver sends packets, the announcer packet idea, and the way HouseMon distinguishes between incoming data and the meta-data inside each driver describing these incoming packets.
A thousand days!
It’s getting a bit repetitive, but I just noticed this:
That’s over 1000 days of sending out one packet a minute on this thing:
… and over 100 days on the recent JeeNode Micro v3:
The battery boost version runs off a single Eneloop AA battery, and is doing fine too:
Onwards!
What if you’re out of wireless range?
Welcome to the weekly What-If series, also available via the Café wiki.
Ok, so you’ve got some JeeNodes up and running, all talking to each other or to a central node via the wireless RFM12B module. Or… maybe not: the signal is too weak! Now what?
There are several approaches you can try to improve wireless range:
- optimise your existing antenna(s)
- lower the data rate and reduce the bandwidth
- use a more advanced type of antenna
- use a directional antenna
- install a repeater of some kind
Let’s go through each of these in turn.
First thing to try is to optimise the little wire “whip” antenna’s that come standard with a JeeNode. Make sure the antenna wire is 82 mm long (that’s for 868 MHz), is sticking up (or sideways) perpendicular to the board, and check that both antenna’s are pointing more or less in the same direction (but not in the direction of the other node: the RF field is circular around the wire, not on top or below).
One thing to keep in mind with these weak signals, is that salty bags of water (us people, that is) tend to absorb RF energy, so these radios work better with us out of the way. Be sure to take a step back while tweaking and hunting for the best orientation!
If that doesn’t help enough, you can do one more thing without messing with electronics or hardware: reduce the datarate of the transmitter and receiver (they have to match). See the RFM12B Command Calculator for settings you can change. To reduce the data rate by two thirds, call rf12_control(0xC614) after the call to rf12_initialize(), for example. The bad news is that you have to do this in all the nodes which communicate with each other – all the data rates have to match!
This in itself won’t extend the range by that much, but with lower data rates you can also reduce the bandwidth in the receiver (with rf12_control(0x94C2)). You can think of this approach as: speaking more slowly and listening more closely. The effects should be quite noticeable. Radio amateurs have been using this technique to get halfway around the world on mere milliwats, using a system called QRSS.
If that doesn’t give you the desired range – here are a few more tricks, but they all require extra hardware: improve the antenna, use “directional” antennas, or use a repeater.
Here’s an example of an improved omni-directional antenna design, as seen on eBay:
And here’s a directional “Yagi” antenna, which needs to be aimed fairly accurately:
I haven’t tried either of these (you can build them yourself), but the omni-directional one was mentioned and described in Frank Benschop’s presentation on JeeDay. He reported getting quite good results, once all the antenna + cabling quirks were resolved.
If neither of these are an option, then the last trick you can try is to add a relay / repeater node to your network, as described in this weblog post some time ago. This will double the range if you place that node in the middle of the two nodes which can’t reach each other, but it adds some complexity to the packet addressing mechanism.
Move over, raspberry
The Raspberry_Pi is a great little board at an amazing little price. But as mentioned yesterday, it’s not very fast as a server. I suspect that a lot of it has to do with the SD card interface and the SD card itself, so I started looking around for alternatives.
And boy, there sure are lots of ‘em – still well below €100. I’ll single out one system, the Odroid U2 – knowing full well that there must be over a dozen others out there:
It’s smaller than a Raspberry Pi, but it comes mounted on a “big” (6x6x6 cm) heat sink.
The specs are pretty impressive:
And the board is neat – the result of a huge mobile phone market driving size down:
Could this be used as central web / file / home automation server?
7 months of sending and still going
My Funky+DS18B20 temperature logging project is still running on that same CR2032 battery ever since my original post back in Oct 31st 2012, that makes it 7 months of run time so far.
I have a live chart here:
Funky+DS18b20 on a CR2032
It is probably at the end of its life, but having said so, probably will kick for a month at least. Amazing stuff.
My other project – Funky+DHT22 is also still running on the original AAA battery, it is located outside and has the purpose of logging outside relative humidity and temperature.
Here are the readings for the period:
(304)
Speedy Raspberry
The Raspberry Pi is an amazing little board, with an amazing amount of power and functionality at an incredible price – it’s probably fair to say that our technology geek’s world will never be the same again, now that we have the RPi.
But it’s no speed monster…
Sometimes during development, it really gets in the way – especially when you’re used to working on a modern fast laptop, which is some 20 times faster (and that’s per-core).
So I decided to overclock one of my RPi’s, and see what it does. Overclocking in Raspbian is trivial with the standard raspi-config utility:
Just go to the Overclock section, and pick one:
I went for the fastest there is, but decided to run a 2-hour test to make sure it really works. Turns out that someone has already done all the work, and even created such a stress test:
root@raspberrypi:~# ./overclock-test.sh Testing overclock stability... reading: 1 945+1 records in 945+1 records out 3965190144 bytes (4.0 GB) copied, 352.455 s, 11.3 MB/s reading: 2 [...] reading: 10 945+1 records in 945+1 records out 3965190144 bytes (4.0 GB) copied, 358.522 s, 11.1 MB/s writing: 1 512+0 records in 512+0 records out 536870912 bytes (537 MB) copied, 95.2065 s, 5.6 MB/s writing: 2 [...] writing: 10 512+0 records in 512+0 records out 536870912 bytes (537 MB) copied, 83.4848 s, 6.4 MB/s ./overclock-test.sh: line 18: 2414 Terminated nice yes > /dev/null CPU freq: 1000000 CPU temp: 58376 [ 5.217175] Registered led device: led0 [ 8.943589] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null) [ 9.418819] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null) [ 19.181046] smsc95xx 1-1.1:1.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 [ 19.431053] bcm2835-cpufreq: switching to governor ondemand [ 19.431082] bcm2835-cpufreq: switching to governor ondemand [ 21.736829] Adding 102396k swap on /var/swap. Priority:-1 extents:1 across:102396k SS [ 22.134893] ip_tables: (C) 2000-2006 Netfilter Core Team [ 22.174573] nf_conntrack version 0.5.0 (7774 buckets, 31096 max) [ 750.951153] smsc95xx 1-1.1:1.0: eth0: kevent 2 may have been dropped Not crashed yet, probably stable.Ya gotta love that last message, nicely semi re-assuring ;)
I did fit a set of cooling fins from Watterott (some nice IR heat pictures there):
As checked with vcgencmd measure_temp, the temperature never rose above 58.4°C.
Onwards!
Logging manualy entered values to emonCMS using keypad
I have finally found some time today to put my keypad project into work, namely I decided to use it for weight logging project here a home. The idea is simple: take measurement using the bathroom scale, then punch in the readout on the keyboard and send for logging. A Funky v2 powered by a CR2032 coin cell battery running this sketch is in power down mode until wakened up by the keypad. The user then has 10 seconds to enter the weight, the ‘*’ acts as decimal point, ‘#’ will reset the entry, if you realize it was wrong. Pressing ‘A’,'B’,'C’,'D’ will send the data for one of the four persons in my family to a NanodeRF gateway that forwards it to my emonCMS installation for logging. Some pictures of the setup (I still need to put all this in decent box):
And it gets visualized like this (some test data in)
Edit: I enclosed the project in a box:
Quite practical (238)