Skip navigation

Who's at the door

 

Hans and Matilda were fast asleep when they heard a knock at the door. He put on a robe and wandered over to the door. "Who is it", he asked, "The postman" replied the stranger. Hans peered through the spyhole and saw the cap of the postman. Why is the postman visiting in the middle of the night thought Hans? He looked again, below the cap he saw a large pair of eyes, above the cap he saw a large pair of hairy ears and through the darkness he saw a large set of sharp teeth. It was the Wolf!

 

Wolf.png

 

He checked the door was securely bolted and headed back to bed. Before he'd even made it to the bedroom there was another knock at the door so he headed back. Peering out of the door this time he saw a bowler hat. "Who is it?" he asked. "It's the Doctor" the hat replied. Hans looked through the hole again. Underneath the hat were two large eyes, a large nose and a large set of teeth. Hans backed away from the door, when there was yet another knock. "Who is he asked", "It's the UPS guy with your Element14 delivery", was the reply. Hans was overjoyed and was just about to open the door when he decided to look through the spyhole again. Again a hatted figure stood outside, and again the figure had large fury ears, large eyes and very large and pointy teeth. Hans went back to bed. That night there was a range of visitors to his door claiming to be the milkman, the window cleaner and finally granny. After that Hans stopped answering the knocks at the door and tried to get to sleep.

 

Knock Knock

 

In the morning Hans had a couple of thoughts, the first was he wanted to upgrade his security and the other was that it might be quite good for the system to check the weather automatically in response to people knocking on the door.

 

Hans realised that there was a buzzer in the Arduino kit and looked into taking that apart to use as a sensor. It did not want to open up easily so he invested in some new sensors, some simple piezo transducers.

PiezoSensor.png

A bit of googling found a suitable circuit for conditioning the sensor signal. The piezo transducer is effectively a voltage source, when the crystal deforms a small voltage is produced. If we put that into a comparator then we can create a strong 0v - 5v swing to indicate the knock. This should be sufficient to wake the Arduino from sleep. A large resistor allows that voltage to discharge and zener diodes stop the inputs being overloaded.

 

Piezo Comparator Circuit

From Thoughts on interfacing piezo vibration sensor - Do It Easy With ScienceProg

 

Looking in the spares cupboard there were a bunch of 741 opamps that could be used for the comparator but checking the spec he realised that they were not designed to work from a 5v supply, and there were also comments that the output swing was less than the rails so some LM393 comparators were also ordered.

 

Excuse me for interrupting

 

Whilst he was waiting for those he did some tests with the interrupts. Reading the Arduino site he learn that only certain pins could be configured as an external interrupt. Looking at the pin out diagram, all of there are taken by the bridge to the Linino module or the I2C bus.

yun-diagram-output.png

from http://www.pighixxx.com/test/pinoutspg/boards/

 

Hans saw a cryptic comment in the Arduino documentation that some of the Atmel chips supported change interrupts on many more pins. But there was no specific reference to the Yún or the ATMega32u4 and no details on how to how to attach the interrupt handler code to the pin. Luckily Matt Walkers article on Pin Change Interupts explained how it all worked and a bit of further digging found Mike Schwager's library that wraps up all the AVR specific commands in a friendly way.

 

Hans tested this firstly in a simple example.

 

#include "EnableInterrupt.h"
int led = 13;
int myint = 11;
volatile int state = LOW;
void setup()
{
   pinMode(led, OUTPUT);
   enableInterrupt(myint, blink, CHANGE);
}
void loop()
{
   digitalWrite(led, state);
}
void blink()
{
   state = !state;
}



 

Then in a power down scenario.

 

#include "EnableInterrupt.h"
#include "LowPower.h"
int led = 13;
int myint = 11;
volatile int state = LOW;
void setup()
{
   pinMode(led, OUTPUT);
   pinMode(myint, INPUT);
   enableInterrupt(myint, blink, CHANGE);
   delay(25000); //Time to reprogramme!
}
void loop()
{
   digitalWrite(led, state);
   LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
void blink()
{
   state = !state;
}



 

Code at: https://github.com/Workshopshed/EnchantedObjects/tree/master/Code

 

These tests proved successful so Hans was happy to make up the circuit once the parts arrived.

 

Reference

http://www.scienceprog.com/thoughts-on-interfacing-piezo-vibration-sensor/

http://www.ti.com/product/lm393

https://github.com/GreyGnome/EnableInterrupt
Arduino - Interrupts
Gammon Forum : Electronics : Microprocessors : Interrupts

Geert's pages - Pin-change interrupts on Arduino

Arduino Pin Change Interrupts | The Wandering Engineer

Hans also found the "pretty-wifi-info.lua" script for checking the Yún's WiFi status, it nicely abstracted Hans code from the hardware so he wrote a wrapper for that rather than writing his own. He used the "parse" module to interpret the output. That installed nicely on the Yún for a change.

 

pip install parse


 

To avoid key errors he defaulted all of the common values to be "unknown".

# Get the Wifi Status into a dictionary
import subprocess
from parse import *

def parselines(s):
    lines = s.splitlines()
    d = {}
    for line in lines:
        p = parse("{}: {}",line)
        if p:
            d[p[0]] = p[1]
    return d

def getWifiStatus():
    w = subprocess.check_output("/usr/bin/pretty-wifi-info.lua")
    p = parselines(w)
    for key in ('Mode','Interface name','SSID','Signal','Encryption method','Active for','IP address','MAC address','RX/TX'):
        p.setdefault(key,'Unknown')
    return p

p = getWifiStatus()

print p['Mode']
print p['Interface name']
print p['SSID']
print p['Signal']
print p['Encryption method']
print p['Active for']
print p['IP address']
print p['MAC address']
print p['RX/TX']

 

Reference

 

https://docs.python.org/2/library/subprocess.html#using-the-subprocess-module

https://pypi.python.org/pypi/parse

https://wiki.python.org/moin/KeyError

Good morning Ricksville

 

One morning Farmer Hogg woke up, looked out the window and checked the colour of his field.He headed down to the kitchen and turned on his internet radio, Rick Astley was playing so he turned it off again.

Old Mother Hubbard turned on her computer to check her inventory management system. A Rick Astley video was playing, she liked Rick so left it playing and forgot what she was about to do.
At the top of the stairs, around the back of the town hall, the man from the Historical society was trying to find film footage of the old mine workings but every time he clicked on a link, Rick Astley appeared.
The inn keeper had Rick Astley playing on his jukebox and also on the POS system.

The woodcutter was normally a man of few words but after 30 minutes trying to rid his computer of Rick, he had managed to find a few extra ones that even the dwarves would have been shocked by.

The mayor turned on his TV to watch Lizzy the Lizard exercise video and also got Rick Astley. Enough was enough, a town meeting was called.


Mean whilst in the forest, Hans and Matilda were trying to connect up to the internet. "Strange?" said Hans, "the requests get past our firewall but timeout when reaching the town ISP, it is there because I can get a response by extending the timeout, but it just seems to be too busy to forward on our weather requests."

 

The old fashioned way


"We are going to have to do it the old fashioned way", said Hans. "Not the cat gut?!" cried Matilda. "Not quite that far back" he said. Hans rummaged in his spares box and brought out a tiny device that looked a bit like a cheese grater. "We can get the local temperature and humidity with this DHT22 and estimate the chance of precipitation from that" said Hans.

 

DHT22_bb.png   DHT22

 

// Based on the work of ladyada, public domain
#include "DHT.h"
#define DHTPIN 4     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
//DHT dht(DHTPIN, DHTTYPE, 30);
void setup() {
  Serial.begin(9600); 
  Serial.println("DHTxx test!");
 
  dht.begin();
}
void loop() {
  // Wait a few seconds between measurements.
  delay(2000);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.print(" *C ");
  Serial.println("");
}




 

Hans decided to pass the local temperature and humidity over to the Python script and if there is no network or an error it can still return a position reference for them. That way all the weather related algorithms are in one place. Hans could not find any algorithms that connected humidity to precipitation but he thought if he based it around the dew point that would give a very similar result to the old cat gut.

 

The boy who cried wolf

 

Mean while at the town meeting a small boy pointed to a logo in the corner of a screen playing Rick Astley videos and cried "wolf! wolf!", the townsfolk told him to be quiet and stop bothering them.

 

Next: Enchanted Objects Design Challenge - This is not the WiFi you are looking for

 

Reference

 

Adafruit Learning - Using a DHTxx sensor

Estimating air humidity from temperature and precipitation measures for modelling applications

How do I calculate dew point?

Precipitation Estimation in Canada using Archival Climate Data - William A. van Wijngaarden* - Physics Dept., York University, Toronto, Ontario

Lecture: Humidity as an Element of Weather, Dr. Rodrigue

Just spotted this, it's the Yún but in a smaller form factor.

 

http://arduino.org/products/arduino-yun-mini

 

A000108-ARDUINO_YUN_MINI_flat1.jpgA000108-ARDUINO_YUN_MINI_tri.jpg

Also spotted it's by the Arduino.org team not the Arduino.cc team if you care about such things.

Putting the Arduino Yun to sleep

 

Hans and Matilda thought back to the Golem and how he slept between each activity, that could also work for their Yún.

  

The key things were:

 

  • Turning the Linino power off
  • Turning the Linino power back on
  • Low power on the ATMega side
  • Waking back up.
  • Timers and servo.

 

Poweroff is not enough

 

The Linino O/S uses BusyBox for a lot of the tasks of it's shell. One of these is the "poweroff" command. http://www.busybox.net/BusyBox.html#poweroff

Running this with the multimeter in the loop to check the current we see that running poweroff makes no difference to the current draw, the Yún still takes 200mA.

 

/*
  Running shell commands using Process class.
  based on http://arduino.cc/en/Tutorial/ShellCommands
*/

#include <Process.h>

int ledPin = 13;                 // LED connected to pin 13

void setup() {
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output

  pinMode(A5, OUTPUT);
  digitalWrite(A5, HIGH);    // sets the Linino on

  Bridge.begin();    // Initialize the Bridge

  Process p;
  p.runShellCommandAsynchronously("poweroff"); // Run in background so process returns

  digitalWrite(ledPin, HIGH);   // sets the LED on
}

void loop() {
}









 

Test points and wired control

 

A discussion on the Arduino forum lead to a part of the schematic that controlled the 3.3v regulator. The RT8010 regulator has a two test points TP51 and TP52 (bridged by a 0ohm resistor). The author kindly points out where those test points are located as there's no silk screen indicating which are which. As per the example the corner I/O pin was used, A5.

YunPower-sch.png

YunResetWire.jpg

Retrospectively they remembered that the A5 pin is shared with the I2C bus on the Uno, luckily this is not the case for the Yún.

The software control for this is pretty straight forward too, it can be controlled as a digital pin. You'd want to wait until any writing to disk was complete before powering off so that will need to be factored into the software. Using that control the consumption drops to 30mA.

 

int ledPin = 13;                 // LED connected to pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  pinMode(A5, OUTPUT);
}

void loop()
{
  digitalWrite(A5, LOW);   // sets the Linino off
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(8000);                  // waits for a 8 seconds
  digitalWrite(A5, HIGH);    // sets the Linino on
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(8000);                  // waits for 8 seconds
}








 

 

You are getting sleepy, very sleepy

But it's possible to even better than that. The commands to put the Arduino to sleep are pretty straightforward even so Hans took the approach of using a library. RocketScream had produced one that made life pretty simple so the code example was extended to incorporate that.

 

//Library from http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/#sthash.PhJ0PF9f.dpuf
#include "LowPower.h"

int ledPin = 13;                 // LED connected to pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  pinMode(A5, OUTPUT);
  delay(25000);                 // Nice long delay to help with reprogramming    
}

void loop()
{
  digitalWrite(A5, HIGH);    // sets the Linino on
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(8000);

  digitalWrite(A5, LOW);   // sets the Linino off
  digitalWrite(ledPin, HIGH);   // sets the LED on

  delay(8000);                  // waits for a second
  digitalWrite(ledPin, LOW);   // both lights off, power and P13

  //Sleep
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}








 

The multimeter uses a different socket for currents over 200mA so a cable swap and photo was taken to get a more accurate reading of the lowest current. For the powerDown the Watchdog timer is used and hence Timer0 which is used for Millis() is turned off and Timer1, used by the Servo() library is also off. This will affect the flashing/colour cycling of the LED and servo so that needs to be factored in the the code.

 

This brings the power down to 2.5mA, approx 80th of the original power required or 33 days of runtime from the battery. Obviously the bursts of activity will bring this down but a week's run time seems achievable.

 

 

IMAG1385[1].jpg

It may also be possible to reduce even more power by permanently turning off those peripherals such as the ADC which are not used although because of the devices used in the project most of the peripherals are used and there may be more effective ways to save power such as minimising the time that the Linino part is powered up.

 

Next: Enchanted Objects Design Challenge - The townsfolk get Rickrolled

 

Reference

 

BusyBox - The Swiss Army Knife of Embedded Linux

Arduino Yun - put linux environment to sleep or halt

Arduino, Zigbee and Embedded Development: Sleeping Arduino - Part 1

http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/

Advanced Arduino: direct use of ATmega counter/timers

<avr/power.h>: Power Reduction Management

Sparkfun Adventures in Low Power Land

C.Defeo's Decorating and Building Merchants

 

Hans and Matilda wanted some sheet metal to build the battery box so popped down to C.Defeo's Decorating and Building Merchants for supplies. The shop keeper advised them that he only had large sheets but he'd cut them for free. He lead Hans and Matilda to the yard out back where the massive sheets of stainless steel were stacked. Hans and Matilda looked up at the sheets and could not work out how the shop keeper was going to move them. He pulled a flute out of his pocket and played a strange tune. From what appeared to be a pile of cement sacks slowly arose a grey brown figure who lumbered over to where they were standing, it was a golem! The shop keeper passed the golem a bottle of ginger beer and he drank it down. The golem turned red then yellow then white and Hans and Matilda realised he was getting very hot so stepped backwards. The golem swiftly and neatly sliced through the metal sheets with his white hot hands before collapsing back onto the cement sacks and falling fast asleep. He does not need much explained the shop keeper, just a few spoonfuls of cement and gingerbeer. "We think he generates acetylene gas which burns internally to produce the heat, not quite sure how it works" he explained, "but it does a good job". "He will now need to sleep for an hour to cool down". The shop keeper explained that he'd been gifted the golem by a Rabbi from Prague in return for some electronic components. Hans and Matilda thanked the shop keeper and returned home with their smaller sheet of metal.

Golem.jpg

 

WARNING!! - Don't mix cement with ginger beer

It probably won't create acetylene but it might create an exothermic reaction or at least make a sticky mess.

 

Bending

Referring to Engineering Workshop Practice 1956 volume III, we can see that the neutral plane for a bend lies 20% of the way through the sheet. Everything on the inside of that will be under compression and everything on the outside will be under tension. We can use this to calculate an allowance for bending.

Bending Allowances from Engineering Workshop Practice Volume IIIBendingAllowancesFromEngineeringWorkshopPracticeVolume32.jpg

The formula for calculating an allowance for bending when the measurements are on the outside of a joint are as follows:

L= A + B - (2 * 0.8)T






 

if the measurements are made on the inside of the joint then it's

L= C + D + (2 * 0.2)T






 

Based on this Matilda sketched a design for the battery box that could be folded out of the metal the golem had cut for them.

 

A box was built based on the sketch and above calculations and the battery fitted perfectly. However, the cable was too short to reach the power board.

Battery Box V1

So a redesign was needed, the side was taken off and it was re-drilled.

BatteryBoxV2.jpg

The rear basement had already been extended to allow for the size of the stack of Arduino and shields. The charging circuit and boosting circuit was moved slightly and the battery and cable now both fitted. The main board was fitted to ensure that there was clearance for all the connectors and that the battery could be removed without needing to disassemble the boards.

BatteryBoxV2Lights.jpgTestFittingTheElectronics.jpg

Some of the cabling was also started with some cables for the LED power and LED made up and a cable for the power also soldered up. The protoshield was wired up with headers for the servo and power supply, for the cables that were undecided they work left long and wrapped over the side of the board. A space was left in the middle of the board for a power mosfet to turn on and off the servo and lighting board.

ProtoBoard.jpgCables.jpg

A productive if not particularly technical week for the project. Next up some more coding and power management and after that if time permits there's still some further enchantments to be applied.

 

Next: Enchanted Objects Design Challenge - Sleeping Golem

As mentioned in a previous installment Hans was having some trouble installing the secure version of the requests module for python, it didn't matter what he tried there always seemed to be something that needed a different version of a tool installing or a script that did not want to run correctly. So Hans took some steps back and wrote the code to get the weather instead.

 

Thinking about the reason for using requests in the first place it was to make the code simpler, however the function to call the API was small and self contained so Hans realised he could swap that out with pycurl instead. So he installed the relevant packages.

 

opkg update
opkg install python-openssl
opkg install python-curl







 

And updated the Python script to use pycurl, he coded it so that either version could be used by swapping out call_api. For the pycurl commands to work an old version of the call was needed, c.setopt(c.WRITEFUNCTION, r.write) rather than c.setopt(c.WRITEDATA, r).

 

from StringIO import StringIO
import pycurl
import json, sys, urllib, urlparse

def get_location():
    with open('/etc/WeatherAPI.conf', 'r') as f:
        location_name = f.readline()
    f.close()
    return location_name


def build_url(location):
    url = "https://query.yahooapis.com/v1/public/yql"
    q = "select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text = '" + urllib.quote(
        location) + "') and u='c'"
    params = {'q': q, 'format': 'json', 'env': 'store://datatables.org/alltableswithkeys'}

    url_parts = list(urlparse.urlparse(url))
    query = dict(urlparse.parse_qsl(url_parts[4]))
    query.update(params)

    url_parts[4] = urllib.urlencode(query)

    return urlparse.urlunparse(url_parts)

def call_api(url):
    r = StringIO()
    c = pycurl.Curl()
    c.setopt(c.URL, url)
    c.setopt(c.CONNECTTIMEOUT, 10)
    c.setopt(c.TIMEOUT, 60)
    c.setopt(c.WRITEFUNCTION, r.write)
    c.perform()
    c.close()
    return r.getvalue()

def map_code(code):
    # Map condition codes to expected precipitation
    # https://developer.yahoo.com/weather/documentation.html
    # 1 = very sunny, 3 = changeable, 5 = very rainy
    codes = {'0': {'n': 'tornado', 'p': '3'},
            '1': {'n': 'tropical storm', 'p': '5'},
            '2': {'n': 'hurricane', 'p': '5'},
            '3': {'n': 'severe thunderstorms', 'p': '5'},
            '4': {'n': 'thunderstorms', 'p': '5'},
            '5': {'n': 'mixed rain and snow', 'p': '5'},
            '6': {'n': 'mixed rain and sleet', 'p': '5'},
            '7': {'n': 'mixed snow and sleet', 'p': '5'},
            '8': {'n': 'freezing drizzle', 'p': '5'},
            '9': {'n': 'drizzle', 'p': '4'},
            '10': {'n': 'freezing rain', 'p': '5'},
            '11': {'n': 'showers', 'p': '4'},
            '12': {'n': 'showers', 'p': '4'},
            '13': {'n': 'snow flurries', 'p': '4'},
            '14': {'n': 'light snow showers', 'p': '4'},
            '15': {'n': 'blowing snow', 'p': '3'},
            '16': {'n': 'snow', 'p': '4'},
            '17': {'n': 'hail', 'p': '4'},
            '18': {'n': 'sleet', 'p': '4'},
            '19': {'n': 'dust', 'p': '3'},
            '20': {'n': 'foggy', 'p': '4'},
            '21': {'n': 'haze', 'p': '3'},
            '22': {'n': 'smoky', 'p': '3'},
            '23': {'n': 'blustery', 'p': '3'},
            '24': {'n': 'windy', 'p': '3'},
            '25': {'n': 'cold', 'p': '3'},
            '26': {'n': 'cloudy', 'p': '3'},
            '27': {'n': 'mostly cloudy (night)', 'p': '3'},
            '28': {'n': 'mostly cloudy (day)', 'p': '3'},
            '29': {'n': 'partly cloudy (night)', 'p': '3'},
            '30': {'n': 'partly cloudy (day)', 'p': '3'},
            '31': {'n': 'clear (night)', 'p': '1'},
            '32': {'n': 'sunny', 'p': '1'},
            '33': {'n': 'fair (night)', 'p': '2'},
            '34': {'n': 'fair (day)', 'p': '2'},
            '35': {'n': 'mixed rain and hail', 'p': '4'},
            '36': {'n': 'hot', 'p': '1'},
            '37': {'n': 'isolated thunderstorms', 'p': '4'},
            '38': {'n': 'scattered thunderstorms', 'p': '4'},
            '39': {'n': 'scattered thunderstorms', 'p': '4'},
            '40': {'n': 'scattered showers', 'p': '4'},
            '41': {'n': 'heavy snow', 'p': '5'},
            '42': {'n': 'scattered snow showers', 'p': '4'},
            '43': {'n': 'heavy snow', 'p': '5'},
            '44': {'n': 'partly cloudy', 'p': '2'},
            '45': {'n': 'thundershowers', 'p': '5'},
            '46': {'n': 'snow showers', 'p': '5'},
            '47': {'n': 'isolated thundershowers', 'p': '4'}}
    state = codes.get(code)
    if not state:
        raise RuntimeError('Unknown weather code returned')
    return state['p']


def parse_weather(json):
    text = json['query']['results']['channel']['item']['condition']['text'].replace(",", " ")
    code = map_code(json['query']['results']['channel']['item']['condition']['code'])
    temp = json['query']['results']['channel']['item']['condition']['temp']
    return {'text': text, 'code': code, 'temp': float(temp)}


def main():
    try:
        loc = get_location()
        weather_url = build_url(loc)
        r = call_api(weather_url)
        j = json.loads(r)
        weather = parse_weather(j)

        print 'OK!,%s,%s,%4.2f' % (weather['text'], weather['code'], weather['temp'])

        return 0

    except Exception, err:
        print 'Err,%s,0,0.0' % str(err).replace(",", " ")
        return 1


if __name__ == '__main__':
    sys.exit(main())







 

The first run reported an error with not being able to verify the certificate so he re-installed the certificates using a slightly modified script that downloaded the certificates from OpenWRT, as the Yun pakcage repository does not seem to have these.

 

#! /bin/sh
OPENSSL=/usr/bin/openssl
CERTDIR=/etc/ssl/certs

opkg update
#opkg install ca-certificates
wget http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/base/ca-certificates_20141019_ar71xx.ipk  
opkg install ca-certificates_20141019_ar71xx.ipk

# Install openssl-util if need
[ ! -f ${OPENSSL} ] && opkg update && opkg install openssl-util

for CERTFILE in ${CERTDIR}/*; do
    # create symbolic link from hash
    echo -en "Certificate ${CERTFILE##*/}\n generating hash: "
    HASH=$(${OPENSSL} x509 -hash -noout -in ${CERTFILE})
    echo "$HASH"

    # handle hash collision
    SUFFIX=0
    while [ -h "${CERTDIR}/${HASH}.${SUFFIX}" ]; do
        let "SUFFIX += 1"
    done

    echo "linking ${HASH}.${SUFFIX} -> ${CERTFILE##*/}"
    ln -s ${CERTFILE##*/} ${CERTDIR}/${HASH}.${SUFFIX}
done

rm ca-certificates_20141019_ar71xx.ipk







 

Running it a second time produced a result. Hans had never been so happy to know that it was Mostly Cloudy in Chicago, IL.

MostlyCloudy.png

Next: Enchanted Objects Design Challenge - The Glowing Golem and shiny battery box

I've mentioned before that we are not the only ones determined to enchant some objects.

 

Simon Morris has made floating lightbulbs powered by induction.

 

 

via:

http://makezine.com/2015/05/03/making-lightbulbs-float/

A useful presentation on securing your devices

 

  1. Defining the Internet of Things (10:27)
  2. Unprotected devices will be attacked (13:15)
  3. Encryption (15:46)
  4. Single security model for all communications (17:56)
  5. Access control (20:13)
  6. Tracking device metadata (21:14)
  7. Provisioning in the field (22:38)
  8. Firmware updates in the field (24:07)
  9. Compliance with regulations (25:15)
  10. Reinventing the wheel (26:17)

 

http://blog.atmel.com/2015/05/04/the-10-challenges-of-securing-iot-communications/

The next challenge for Matilda was a temperature gauge, she'd planned to use an LED bargraph for this but was concerned it would "light up the house like a Christmas tree". Her next thought was a servo driven slider pointing at a scale. There was not much room for this so she wondered if she needed to bother with a Fahrenheit scale. She'd ask the oldest person she knew which was Farmer Hogg. It was lunch time so she knew where to find him, in the Adam and Eve.

 

Farmer Hogg

 

Matilda arrived at the inn and soon spotted Farmer Hogg with a shepherd's pie and a tankard of ale. She showed him her notebook with the plans for the temperature gauge and asked him if he used Celsius or Fahrenheit. "I divn't bother with tweither" he retorted. "So how do you tell the temperature?" asked Matilda. Farmer Hogg looked down at his empty tankard and back up at Matilda. This was going to be a long story and Matilda hoped it would not cost her too much in beer to hear it out.

Matilda returned presently with two tankards, "Happen ah rises" started Farmer Hogg, "ah looks oot on fell an happen aal oer with white snow happen jumper n jacket, happen green with grass, " Farmer Hogg paused and took a large swig from his drink, "happen oor shirt, tupping n raddling, happen brimming yellow with lockity gowan happen vest n sheerlings" , Matilda took a swig from her own tankard to see of it might aid her comprehension. As she placed her drink back on the table Farmer Hogg tapped his empty tankard on the brim, "get yasells yan". Matilda finished her drink and got two refills from the bar. "Happen purple fell with heather" Farmer Hogg continued, "happen jacket, backend, feltle pens, snag the neeps. Happen that till be that" Farmer Hogg concluded and Matilda looked at him puzzled. Farmer Hogg looked annoyed and snatched the notebook.

 

He scribbled the following:

White Snow

Green Grass

Yellow Flowers

Purple Heather

 

Matilda thanked the farmer and staggered home, she waved the paper triumphantly at Hans before collapsing in an arm chair and falling fast asleep.

 

Matilda sees the light

 

In the morning Matilda was suffering from her "lunch" with Farmer Hogg. But she wrote up her notes from the meeting. She explained to Hans that the idea was, rather than having a complex display for the temperature they could use an RGB LED to show the temperature and status. They could use the Infineon shield, not because they needed it's power driving capability but because it could offload some of the processing. Hopefully it would also make the Arduino code simpler too.

 

ColourTemperature°C / Status
White<0 - below zero aka Ice
Purple0 - 5
Blue5 - 10
Green10 - 15
Yellow15 - 25
Orange25 - 30
Red30 +
OffOff / Sleeping
Slow FlashBooting / Getting data
Quick FlashError (Using Historic or Local Data)
Colour cycleNeeds configuring

 

 

How low can you go?

 

The Infineon shield does not implement large resistors to limit the current through the LEDs, rather it senses the current flow as a voltage over a small sense resistor and adjusts the modulation of the driving MOSFET based on that. To vary the current a reference voltage can be configured. It should also be possible to bring the average current down by increasing the off time parameter which in turn increases the LED current ripple.

LED Current Sensing LED Current Ripple

The data sheet did not provide a calculation for the current, recommending an experimental technique using an oscilloscope, it also had a big table full of examples. These values were plotted and a trend line added to produce a formula to calculate current from input parameter.

Estimate Equation

That gave a value of 3 representing 18mA or 2 representing 11mA which might be a safer starting point. The average current could then be measured with a multimeter as an oscilloscope was not available.

 

Standing on the shoulders of giants

 

Rather that starting from scratch Hans decided that he could use one of the code libraries already created during the Holiday Lights challenge which are in turn wrappers for the Infineon library. Using jancumps' review the library from ipv1 was selected.

 

The first test was to see if it was possible to drive a regular red LED with no current limiting resistor. Based on the above graph/equation, the "max current" setting was set to 1, it's lowest value (although 0 has not been tried). A multimeter was put in series with the LED to measure the current. This read a little high at 24mA so the off time parameter was incremented and successfully brought that back down to 20mA. Then a little programme was written to sweep the brightness up and down. The other thing that was tested was that the shield could be run from just 5v rather than needing a higher supply, Hans had already checked the schematic, the regulator and microcontroller on the shield were capable of running at the lower voltage. This would simplify the circuitry. The Arduino was powered from an adapter and the shield from the battery with Adafruit boost regulator.

 

Code at Github

 

Now that the system had been proven using a cheaper red LED the jumbo RGB LED could be swapped in with reduced risk of a costly burn out. The brightness was set at a mid level and code changed to cycle through the colours.

 

Code at Github

 

Whilst the circuit was being powered off it was noted that the LED stayed the same colour even once the Arduino was powered off. That could come in handy.

 

A small PCB had been considered for the LED but given that it fitted ok into the breadboard and that there are no other components than a connector, a simple stripboard will be used with some form of fastening to hold it into the wooden frame. Standoffs attached with glue have previously shown to work.

 

Reference:

http://www.lakelanddialectsociety.org/dialect_glossary.htm

http://www.element14.com/community/docs/DOC-70582

 

Next: Enchanted Objects Design Challenge - Taming the Python

Hans was struggling with installing requests[security] the compile issues seemed to keep coming back like a hydra regrowing its heads.

 

To take a break he went to visit his friend Albert. Albert invited Hans in and disappeared into the kitchen to make some tea. "Make yourself at home" called Albert from the other room. Hans sat down on the sofa next to a grey cat. It looked friendly so Hans went to pet it. As soon as he moved the cat stretched out its paw and out shot the claws. Hans recoiled narrowly avoiding a serious injury. "Ah, I see you've met, Injector" said Albert as he came back in with a tray of tea and biscuits. Albert grabbed a throw from the back of the sofa and deftly wrapped the cat in it. The cat peered up at Albert and purred contently.

 

SamCat.jpg

Photo Credit: "Sam cat" by Alan Barnet

When he returned home, Hans decided to work on the python code and roughed out the following high level design.

 

Steps
Get Location
Generate URL
Check URL
Parse Response
Map Weather Codes

 

He had considered using the users IP address to identify location but as his Google search page kept sending him to Google.pl and Microsoft thought his office was in the USA he was not so sure on this approach. Rather, he decided to read the value from a file and hopefully would later have some time to change the UI to allow the user to enter the location. If the users were supplying the location he'd need to ensure his code was protected from parameter injection by correctly wrapping and encoding the provided parameters.

 

This is the resulting python code.

 

import requests, json, sys, urllib, urlparse


def get_location():
  with open('/etc/WeatherAPI.conf', 'r') as f:
  location_name = f.readline()
  f.close()
  return location_name


def build_url(location):
  url = "https://query.yahooapis.com/v1/public/yql"
  q = "select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text = '" + urllib.quote(location) + "') and u='c'"
  params = {'q': q, 'format': 'json', 'env': 'store://datatables.org/alltableswithkeys'}

  url_parts = list(urlparse.urlparse(url))
  query = dict(urlparse.parse_qsl(url_parts[4]))
  query.update(params)

  url_parts[4] = urllib.urlencode(query)

  return urlparse.urlunparse(url_parts)


def call_api(url):
  r = requests.get(url, timeout=(10, 60)) # Connection timeout and read timeout
  if r.status_code != 200:
  raise RuntimeError('API Call Failed(%s)' % r.status_code)
  return r


def map_code(code):
  # Map condition codes to expected precipitation
  # https://developer.yahoo.com/weather/documentation.html
  # 1 = very sunny, 3 = changeable, 5 = very rainy
  codes = {'0': {'n': 'tornado', 'p': '3'},
  '1': {'n': 'tropical storm', 'p': '5'},
  '2': {'n': 'hurricane', 'p': '5'},
  '3': {'n': 'severe thunderstorms', 'p': '5'},
  '4': {'n': 'thunderstorms', 'p': '5'},
  '5': {'n': 'mixed rain and snow', 'p': '5'},
  '6': {'n': 'mixed rain and sleet', 'p': '5'},
  '7': {'n': 'mixed snow and sleet', 'p': '5'},
  '8': {'n': 'freezing drizzle', 'p': '5'},
  '9': {'n': 'drizzle', 'p': '4'},
  '10': {'n': 'freezing rain', 'p': '5'},
  '11': {'n': 'showers', 'p': '4'},
  '12': {'n': 'showers', 'p': '4'},
  '13': {'n': 'snow flurries', 'p': '4'},
  '14': {'n': 'light snow showers', 'p': '4'},
  '15': {'n': 'blowing snow', 'p': '3'},
  '16': {'n': 'snow', 'p': '4'},
  '17': {'n': 'hail', 'p': '4'},
  '18': {'n': 'sleet', 'p': '4'},
  '19': {'n': 'dust', 'p': '3'},
  '20': {'n': 'foggy', 'p': '4'},
  '21': {'n': 'haze', 'p': '3'},
  '22': {'n': 'smoky', 'p': '3'},
  '23': {'n': 'blustery', 'p': '3'},
  '24': {'n': 'windy', 'p': '3'},
  '25': {'n': 'cold', 'p': '3'},
  '26': {'n': 'cloudy', 'p': '3'},
  '27': {'n': 'mostly cloudy (night)', 'p': '3'},
  '28': {'n': 'mostly cloudy (day)', 'p': '3'},
  '29': {'n': 'partly cloudy (night)', 'p': '3'},
  '30': {'n': 'partly cloudy (day)', 'p': '3'},
  '31': {'n': 'clear (night)', 'p': '1'},
  '32': {'n': 'sunny', 'p': '1'},
  '33': {'n': 'fair (night)', 'p': '2'},
  '34': {'n': 'fair (day)', 'p': '2'},
  '35': {'n': 'mixed rain and hail', 'p': '4'},
  '36': {'n': 'hot', 'p': '1'},
  '37': {'n': 'isolated thunderstorms', 'p': '4'},
  '38': {'n': 'scattered thunderstorms', 'p': '4'},
  '39': {'n': 'scattered thunderstorms', 'p': '4'},
  '40': {'n': 'scattered showers', 'p': '4'},
  '41': {'n': 'heavy snow', 'p': '5'},
  '42': {'n': 'scattered snow showers', 'p': '4'},
  '43': {'n': 'heavy snow', 'p': '5'},
  '44': {'n': 'partly cloudy', 'p': '2'},
  '45': {'n': 'thundershowers', 'p': '5'},
  '46': {'n': 'snow showers', 'p': '5'},
  '47': {'n': 'isolated thundershowers', 'p': '4'}}
  state = codes.get(code)
  if not state:
  raise RuntimeError('Unknown weather code returned')
  return state['p']


def parse_weather(json):
  text = json['query']['results']['channel']['item']['condition']['text']
  code = map_code(json['query']['results']['channel']['item']['condition']['code'])
  temp = json['query']['results']['channel']['item']['condition']['temp']
  return {'text': text, 'code': code, 'temp': float(temp)}


def main():
  try:
  loc = get_location()
  weather_url = build_url(loc)
  r = call_api(weather_url)
  j = json.loads(r.content)
  weather = parse_weather(j)

  print 'OK!,%s,%s,%4.2f' % (weather['text'], weather['code'], weather['temp'])

  return 0

  except Exception, err:
  print 'Err,%s,0,0.0' % str(err).replace(",", " ")
  return 1


if __name__ == '__main__':
  sys.exit(main())










 

For the test location of Chicago,IL the report came out as

 

OK!,Fair,2,16.00

 

Changing the URL to one with a known invalid security certificate returns the following:

 

Err,[Errno bad handshake] [('SSL routines'  'ssl3_get_server_certificate'  'certificate verify failed')],0,0.0




 

Back into Arduino

 

So the next job on the coding is on the microcontroller side to parse this string returned from the API and move the servo and light the lights accordingly. The issue with the requests[security] install will also need to be resolved some how.

 

Next: Enchanted Objects Design Challenge - Farmer Hogg and the Lockity Gowan

 

Reference

 

File reading

https://docs.python.org/2/tutorial/inputoutput.html

 

URL Encoding

http://stackoverflow.com/questions/1695183/how-to-percent-encode-url-parameters-in-python

 

URL Building

https://docs.python.org/2/library/urlparse.html

 

Validate certificates

http://docs.python-requests.org/en/latest/user/advanced/

 

Parsing the JSON

https://docs.python.org/2/library/json.html

 

Mapping via a dictionary

http://learnpythonthehardway.org/book/ex39.html

Ever since the storm Hans and Matilda's power supply had been quite flaky. The electricity company had sent engineers round several times who found and fixed loose connectors and faulty wiring deep in the forest. But the problems kept occurring so Matilda was keen to get their battery based supply up and running.

MatildaAndBattery.jpg

 

The Blue Haired Woman

 

On the day that Matilda planned to connect up the Yun they had a knock on the door. Hans opened the door and was greeted by a large blue ball of fur, carrying a pie. "Hello Hans" said Mrs Spratt's voice from inside the ball. Hans invited her in and they went through to the kitchen where Matilda was busy soldering. A space was cleared for the pie and Hans found a knife and plates so they could all have a piece. Mrs Spratt explained that she'd found an old shampoo recipe made from blueberries that was supposed to make your hair stronger and full bodied. It was not till after she tried it out that she read that it sometimes had side effects. She'd had a few berries left over so had decided to make a pie for Hans and Matilda. Mrs Spratt had been eating whilst she was talking so Hans washed up the empty pie dish and Mrs Spratt took it home.

 

Off Grid Living

 

Matilda was keen not to have any unexpected side effects with her battery and power so she built a simple circuit on the breadboard to test it.

PowerTest.jpg

The AdaFruit board that has been selected provides 5.2v rather than 5v so the schematic was examined and each of the datasheets checked to avoid an expensive mistake.

 

ComponentData Sheet
Max Supply Voltage
ATMega3u4http://www.atmel.com/devices/atmega32u4.ATmega32U4?tab=parameters5.5v
RT8010 - 3.3v Regulator for the MIPS Processorhttp://www.richtek.com/download_ds.jsp?s=2825.5v
MAX3375E - Bridge Level Shifterhttp://www.maximintegrated.com/en/products/interface/level-translators/MAX3375E.html/tb_tab05.5v
NTB0104 - ICSP Level ShifterNTB0104UK :: NXP Semiconductors5.5v
NTB0102GF - Handshake Level ShifterNTB0102GF :: NXP Semiconductors5.5v
AU6350 - USB hub and card Readerhttp://wenku.baidu.com/view/6c347a4ac850ad02de8041905.5v

 

The voltage across the LED and resistor were measured and was around 5.1v so comfortably in the range of all of these components.

 

Mounting the Yún

 

There are several engineering drawings for the Arduino series explaining where the holes are located, it's also possible to use a board as a template to mark the holes. After looking at a selection mounting plates on Thingiverse, Matilda decided to go for 3mm threaded rods, captive nuts and some spacers.

PinsAndBoards.jpg

Ref:

 

The Arduino Yún provided it's own challenges here. The SD card is right next to the mounting hole so makes it difficult to put in a spacer. The height of the 90° USB and Network sockets are particularly high so long pins are needed. The stacking headers found from CPC did not have enough clearance so were swapped those with the long pins provided in the kit and then soldered the shortened stacking headers on top. The Infineon board could then be used with standard length pins.

CaptiveNuts.jpgTestFitting.jpg

The protoshield also threw in it's own curveball having only 3 out of the 4 standard mounting holes. With the test fitting it's fairly sturdy so one of the screw threads can be shortened to just support the Yún.

 

The battery will also need mounting somewhere, perhaps a battery box strapped to the back of the house? This is also a challenge as the pre-wired cable is quite short.

 

The Wolf

 

Meanwhile in the forest the wolf put away his wire cutters and realised he'd need to find another way to sabotage the project.

I discovered this morning that back in 1945 there was a film called the "Enchanted Cottage" perhaps there will be a remake?

FilmPosterMod.jpg

Package Manager

All modern Linux distributions come with a package manager such as Yum or RPM. The Linux distribution included on the Arduino Yun is no exception. It uses OPKG (Open PacKaGe manager).

To get an upto date list of package you use the command opkg update to list the package available opkg list and there's install, update and remove commands for actually managing the packages. The instructions are covered in details in the link above.

 

Configuration

You can change the behaviour of OPKG via a configuration file /etc/opkg.conf . This contains the details of where OPKG downloads the packages from and where they are installed to. It can also incorporate signing and proxy settings if you need those for your system.

 

Sources

When you install an image to the Yun it contains some default locations where the package manager can look for new packages. And most of the time that's fine. However, if you find yourself not being able to install a third party component, in my case Python's requests[security] package. Then you might want to check some other package repositories. Note that some of these locations have packages for multiple systems so for the Arduino Yún you want to look for the "generic ar71xx" branch.

 

Arduino.cc

http://downloads.arduino.cc/openwrtyun/1/packages/

OpenWRT

http://downloads.openwrt.org/

Linino

http://download.linino.org/

 

Warning!

You may find that using other sources for packages causes things to fail. This is because the image creators have been very specific in what packages they put together to ensure they all work. Mixing packages is almost guaranteed to cause you additional work. What you need to go is to unpick the chain of packages for your problem installation. Once you've done this you can remove the old packages and re-install from the new repository.


Creating Packages

If you've got a lot of components you have created to put on your Yún and want to deploy to several devices then creating your own ipk packages might be a good solution.

Currently...

 

Whilst Hans was busy coding, Matilda was looking into power requirements. She was worried that the batteries might take a long time to deliver so wanted to order them long before they would be needed.

 

DevicePower Required
Arduino Yun300mA
MicroSD Card100mA
Infineon RGB LED controller9mA
Servo100mA
RGB LED 20mA per colour60mA

 

Totting up the numbers she arrived at 569mA peak consumption, she realised that by turning things off and running tasks in series that number could be reduced. She also concluded that if they only checked the weather a few times an hour then their overall consumption could be reduced too.

Power.png

 

Based on these numbers she concluded that a 2000mAh battery would give them several days run time. She would need to measure the actual consumption once the circuits were assembled.

Given the small size of the cottage, a Lithium Polymer battery gave the best size to capacity, it was also easily capable of providing the peak power requirements. The PowerBoost 500 from Adafruit was selected to charge the battery and also boost the 3.7v of the battery up to 5v needed by the Yun.

 

The Flaming Postman

The next morning Matilda was telling the postman about her purchase and he explained that they could not deliver her battery. They'd stopped taking LiPo batteries after that time when old Bob's hair caught fire after a battery exploded in his sack. He was half way to the next village before someone caught up with him and helped put out the fire. "I smelt something but thought it was that pudding lane pie shop" he had said.

 

The blind man and a trip to the market

Matilda would need to collect the battery herself so grabbed her basket and headed off to the market. On the way to the market she met and old blind man carrying a basket of apples. She walked with him for sometime and chatted about the work on the cottage. As they approached the market some small boys ran up and each took apples from the man's basket, the old blind man appeared not to notice so Matilda shouted at the boys. Matilda apologised to the old blind man that she could not stop them. "I used to wave my stick at them" explained the old blind man "but that was very tiring, so now I just wear this blindfold so I don't have to watch them taking my apples". "So you're not actually blind then?" asked Matilda. "Oh, no dear", said the old man with a blindfold. Matilda said farewell and popped into the supply office to collect her battery.

PowerSchematics.png

When Matilda returned from the market with the battery she found Hans still struggling to get the appropriate modules to compile for secure python requests. "Can you believe that everyone just recommends turning off the warning messages" exclaimed Hans. Yes, Matilda could.

 

Next: Enchanted Objects Design Challenge - The Blue Haired Woman and Off Grid Living