FHT8v direct control

IMPORTANT: only works with CUL V3 or newer and culfw Version 1.30 or newer!

TFHT protocol (static T)T
HHHHHousecode hexadecimal12342. room 1334; 3. room 1434 etc. Increment 1st byte by one.
DDValve number hexadecimal (up to 8 devices per room)00All valves in a room are addressed
01Valve 1
02Valve 2
CCCommand2fDevice pairing command
A6Open valve to value VV % (8bits hexadecimal)
VVValue000% or pairing commandDesired valve position * 255 / 100 = decimal value.
Convert the decimal value into the hexadecimal value.
1910%
3320%
4c30%
8552%
FF100%

EXAMPLE: T123400A64C opens all valves in room 1234 to 30%.

Everything comes together for a 1st prototype

This week my 1st self designed PCBs arrived from eurocircuits.com.

Below you see the frontside view, which is holding basically all components, more to that later.
PCB front

This is the PCB backside where actually only the 2X13 PIN connector goes in.
PCB backside

I used some one-way plastic soup bowls to assort the components for the three prototypes.
Assorted components

In the step below all resistors and the two ICs (MCP 3008 and MCP 23S17) have been soldered to the board.
ICs added

Almost there, connector for PIR and IR proximity added, DHT22 (Temperature & Humidity Sensor) and 7-segment displays added.
DHT22 and connector for IR proximity added

Completely assembled it looks like this.
Fully loaded shield prototype

To put it on the RaspberryPi I needed some extra tall stacking headers.
Stacking header für Raspberry Pi (extra tall)

Finally, this is how the shield looks when it is added to the Raspberry Pi.Prototype Shield on Raspberry Pi

7 Segment Display with MCP23S17

The temperature shall be displayed by using two 7 segment displays. To save some of the GPIO ports of the Pi the way of choice was a port expander. I decided to use the MCP23S17 which I bought over here. The MCP23S17 is controlled via the SPI bus, which comes in handy, as it is possible to extend the display very easily by adding new 7 segment units and additional MCP23S17s on the same bus. The port expander provides two banks with 8 ports each which is just enough to steer one 7 segment display.

7Segment mit MCP23S17
The picture above shows the layout in the Fritzing software.

7Segment mit MCP23S17
And this one how it actually looks on the breadboard.

The script is called with two parameters, e.g. perl ./7segments.pm 1 2. In this case this would generate the number 12 to be displayed. Every parameter different to a number from 0-9 turns the respective 7 segment display off.

#!/usr/bin/perl

use Device::BCM2835;
use strict;

# call set_debug(1) to do a non-destructive test on non-RPi hardware
# Device::BCM2835::set_debug(1);
Device::BCM2835::init()
|| die "Could not init library";

# Variables
my $test;
my $param1;
my $param2;

# read CLI params
($param1, $param2) = @ARGV;

if ($param1 !~ /[\d]/ || $param1 > 10) {
 $param1 = 10;
}

if ($param2 !~ /[\d]/ || $param2 > 10) {
 $param2 = 10;
}

# MCP23S17 Values
my $SPI_SLAVE_ADDR = 0x40;
my $SPI_IOCTRL     = 0x0A;
my $SPI_IODIRA     = 0x00;
my $SPI_IODIRB     = 0x01;
my $SPI_GPIOA      = 0x12;
my $SPI_GPIOB      = 0x13;

# MCP23S17-PINs
my $SCLK = 11;  # PIN11 = Serial-Clock
my $MOSI = 10;  # PIN10 = Master-Out-Slave-In
my $MISO = 9;   # PIN9  = Master-In-Slave-Out
my $CS   = 24;  # PIN24 = Chip-Select

# Digit Values
my @output10 = ( 0b10000001, 0b11100111, 0b10010010, 
                 0b11000010, 0b11100100, 0b11001000, 
                 0b10001000, 0b11100011, 0b10000000, 
                 0b11000000, 0b11111111 );
my @output1  = ( 0b10000001, 0b11111001, 0b01000101,
                 0b01100001, 0b00111001, 0b00100011,
                 0b00000011, 0b11110001, 0b00000001,
                 0b00100001, 0b11111111 );

# Set RPi pin 11 to be an OUTPUT
Device::BCM2835::gpio_fsel($SCLK, BCM2835_GPIO_FSEL_OUTP);
# Set RPi pin 10 to be an OUTPUT
Device::BCM2835::gpio_fsel($MOSI, BCM2835_GPIO_FSEL_OUTP);
# Set RPi pin 9 to be an INPUT
Device::BCM2835::gpio_fsel($MISO, BCM2835_GPIO_FSEL_INPT);
# Set RPi pin 24 to be an OUTPUT
Device::BCM2835::gpio_fsel($CS, BCM2835_GPIO_FSEL_OUTP);

# prepare the edge
Device::BCM2835::gpio_write($CS, 1);
Device::BCM2835::gpio_write($SCLK, 0);

# subroutine sendValue
sub sendValue {
 # send value
 my $i = 0;
 my $value;
 ($value) = @_;
 while ($i < 8) {
   if ($value & 0x80) {
     Device::BCM2835::gpio_write($MOSI, 1);
   } else {
     Device::BCM2835::gpio_write($MOSI, 0);
   }
   # generate falling edge for the clock signals
   Device::BCM2835::gpio_write($SCLK, 1);
   Device::BCM2835::gpio_write($SCLK, 0);
   $value <<= 1; # shift bit 1 position to the left
   $i ++;
 }
}

# subroutine sendSPI
sub sendSPI {
 # CS active (LOW-Aktiv)
 Device::BCM2835::gpio_write($CS, 0);

 my($opcode, $addr, $data);
 ($opcode, $addr, $data) = @_;

 $test = &sendValue($opcode); # send OP-Code
 $test = &sendValue($addr);   # send address
 $test = &sendValue($data);   # send data

 # CS not active
 Device::BCM2835::gpio_write($CS, 1);
}

# Initialise MCP23S17
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_IODIRB, 0x00); # GPPIOB as INPUT
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOB, 0x00);  # Reset GPIOB
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_IODIRA, 0x00); # GPPIOA as INPUT
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOA, 0x00);  # Reset GPIOA

# Send Data
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOB, $output10[$param1]);
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOA, $output1[$param2]);

The great tutorial from Erik Bartmann which you can find over here helped me a lot to get this running. You may want to check out his site http://erik-bartmann.de.

IR distance sensor

I want the (still to be added) display only to be powered up when someone is within the range of the device to save some energy. For the implementation of this function I decided to start with an already assembled IR distance sensor from Sharp.

As this sensor is an analog sensor the analog voltage out will range from 3V when an object is only 10 cm away and 0.4V when the object is 80 cm away. Unfortunately the Pi does not have any analog inputs.

My rescue was the great post from Matt @ raspberry-spy.co.uk, where he explains how to measure different light levels on the Raspberry Pi.

So I started from re-building his circuit and run some test measurements, this is how it looked on my breadboard.
LDR with capacitor

For a detailed overview including the Fritzing views please check out Matt’s post. Once I had replicated this set-up successfully I added the IR distance sensor.IR distance sensor on breadboard

With the following code I am able to count how many loops it takes until the capacitor voltage has increased enough to be considered as a HIGH by the GPIO pin (approximately 2V). The number of loops is proportional to the distance of an object in front of the sensor.

#!/usr/bin/perl

use Device::BCM2835;
use strict;

# call set_debug(1) to do a non-destructive test on non-RPi hardware
# Device::BCM2835::set_debug(1);
Device::BCM2835::init()
|| die "Could not init library";

# Variables
my $ir_pin = 24;
my $measurement =0;

# logfile handling
sub logging {

  my $logfile = "/appco.de/log/appco.de.log";

  if ( ! open LOG, ">>", $logfile ) {
    die "Kann Logdatei nicht anlegen: $!";
  }

  my ($sekunden, $minuten, $stunde, $tag, $monat, $jahr) = localtime;
  my $echtes_jahr = $jahr + 1900;
  my $echter_monat = $monat + 1;
  printf LOG "%s.%02s.%02s %02s:%02s:%02s %s\n", $echtes_jahr, $echter_monat, $tag, $stunde, $minuten, $sekunden, $_[0];
  close LOG;

}

while (1){
  # Discharge capacitor
  # Set GPIO pin to OUTPUT
  Device::BCM2835::gpio_fsel($ir_pin, BCM2835_GPIO_FSEL_OUTP);
  # Set GPIO pin to LOW
  Device::BCM2835::gpio_write($ir_pin, LOW);
  sleep (0.1);

  # Set GPIO pin to INPUT
  Device::BCM2835::gpio_fsel($ir_pin, BCM2835_GPIO_FSEL_INPT);

  $measurement = 0;

  # Count loops until voltage across
  # capacitor reads high on GPIO
  while (Device::BCM2835::gpio_lev($ir_pin) == 0){
    $measurement ++;
    sleep (0.2);
    # stop measuring after 100.000 loops
    if ($measurement > 100000){
      &logging ("canceled");
      last;
    }
  }

  &logging ("$measurement");

}

At the moment the sensor is always powered on, which is probably wasting more energy than I am intending to save by the use of the sensor.

For the future the sensor should only be powered up when the PIR sensor detected a movement and I also want to replace the ootb sensor with a much cheaper solution made out of IR LEDs and an IR receiver.

Posted in Uncategorized | 1 Reply

Temperature and humidity sensor

To control the heating, the Pi needs to know temperature and humidity, this is possible by using the combined sensor DHT22. I got my unit from Adafruit here. It comes with the required 4.7K – 10K resistor, to be used as a pullup from the data pin to VCC. How the wiring on the breadboard works you can see depicted further below.

Initially I wanted to interface the DHT22 temperature and humidity sensor with perl. After some time it became obvious that perl on the Pi is not fast enough to read successfully from the sensor.

At that point I decided to use the great C-code from Adafruit (available on Github) and simply embed it into my perl script. A very useful tutorial from Adafruit is available here.

The picture below shows how the wiring looks like on the breadboard
Temp/Hum Sensor

This is how this translates into the Fritzing breadboard view
Temp/Hum Fritzing

The script calls the Adafruit C-code with the parameters 22 (for the sensor type) and 4 (which is the GPIO pin to be used). As even this code is not able to perform a successful measurement at every run I created a small loop to ensure that the logging only happens when the values have been extracted successfully. You may also notice the counter variable in the code, this variable can be used to track how many loops are required until a successful measurement could be taken. In practice the values are between 2 and 5 loops, maximum I noticed so far was 11.

#!/usr/bin/perl

# logfile handling
sub logging {

  my $logfile = "/appco.de/log/appco.de.log";

  if ( ! open LOG, ">>", $logfile ) {
    die "Kann Logdatei nicht anlegen: $!";
  }

  my ($sekunden, $minuten, $stunde, $tag, $monat, $jahr) = localtime;
  my $echtes_jahr = $jahr + 1900;
  my $echter_monat = $monat + 1;
  printf LOG "%s.%02s.%02s %02s:%02s:%02s %s\n", $echtes_jahr, $echter_monat, $tag, $stunde, $minuten, $sekunden, $_[0];
  close LOG;

}

my $bin = './Adafruit_DHT 22 4';
my $check = 0;
my $counter = 0;

#run until a temperature and humidity value has been logged
while ($check == 0){
  # run the C program
  $result2 = `$bin`;

  # extract the strings
  my @array = split("\n", $result2);

  $counter = $counter + 1;

  # logging only if the string is not empty
  if ($array[2] ne "") {
    &logging ("$array[2]");
    &logging ("$counter");
    $check = 1;
  }
}

PIR sensor

As I would like my HomeAutomation to learn my schedule I need to give the Pi some eyes. Let’s start with a PIR (passive infrared) sensor.
The Fritzing screenshot below shows how the sensor is wired up to the cobbler. Basically the red wire goes to 5V0, the black wire to GND and the yellow data wire is hooked up to #25.

PIR Fritzing

As an initial test the following statement executed from the command line served me well

while true; do gpio read 6; done

This reports a 0 when the PIR is not triggered and a 1 when triggered.

As a next step I replicated the very same functionality in a basic perl script using WiringPi-Perl.

#!/usr/local/bin/perl -w</code>

use lib "/appco.de/WiringPi-Perl";

require "wiringpi.pm";

if (wiringpic::wiringPiSetup () == -1)
{ exit 0};

# set pin #6 (marked with #25 on the T-Cobbler) to mode INPUT
wiringpic::pinMode (6, 0);

while (1){
  # read from PIR

  # PIR not triggered
  if (wiringpic::digitalRead (6) == 0){
    print ("off \n");
    wiringpic::delay (500); # milliseconds
  }

  # PIR triggered
  if (wiringpic::digitalRead (6) == 1){
    print ("on \n");
    wiringpic::delay (500); # milliseconds
  }
}

This code writes “off” to the standard out when the PIR is not triggered and “on” when triggered until you stop the script with ctrl+c.

Raspberry Pi and sensors

Inspired by the Nest® learning thermostat I want to improve the HomeAutomation capabilities of the Raspberry Pi by adding some sensors to enhance the functionality.

Temperature and humidity sensor
To measure the rooms temperature and humidity and to control the electrical valve accordingly. The reason to choose the sensor DHT22 over the DHT11, is the much higher precision. For example for temperature measures: ±0.5°C accuracy (DHT22) vs. ±2°C accuracy (DHT11). To my believe ±2°C is not acceptable for steering the temperature in a room.
Temp/Hum Sensor
Temp/Hum Sensor (on the right hand side) already hooked up to the T-Cobbler on a breadboard

PIR
The Pi should be able to notice whether someone is in the room and regulate the temperature accordingly. Over time the server should be able to build a schedule and maintain this schedule. I’ll use this sensor from adafruit.com
PIR Sensor

IR distance / proximity
With this sensor the server should be able to detect a human being close to itself and enable interaction by making the user inteface available. For the time being I will work with the Sharp GP2Y0A21YK0F and may move to a DIY version later on.
IR Distance Sensor

Raspberry Pi as HomeAutomation server

Finally my Raspberry Pi has arrived and I want to use it as the server for the perl based HomeAutomation server fhem http://fhem.de/fhem.html.

Therefore my Pi has been upgraded with a micro USB WLAN stick and a CUL device from Busware http://busware.de/tiki-index.php?page=CUL running culfw http://culfw.de/culfw.html

Raspberry Pi overview

For the fhem set-up I followed the installation instruction as described under http://www.fhemwiki.de/wiki/Raspberry_Pi and this worked like a charm

The installation of the culfw firmware was a bit more tricky, but with the following steps I was able to flash the CUL to the latest version.

Download the firmware
sudo wget http://culfw.de/culfw-1.46.tar.gz
and unpack it
sudo tar -zxvf culfw-1.46.tar.gz

Change into your device directory (e.g. Devices/CUL)
cd /home/pi/CUL_VER_146/culfw/Devices/CUL
Install the package dfu-programmer
sudo apt-get install dfu-programmer
Insert the device into the USB slot while pressing the micro-switch
Finally execute
sudo make usbprogram_v3 V3 to be used for CUL V3.
After flashing the CUL, a new USB device should appear: “03eb:204b Atmel Corp.”. If not re-insert the device without pressing the micro-switch.

The server is now up and running since several days.  For the time being the server is just listening to the FS20 traffic in the air and logs it.

T4F4C00B600F7
T430D00362601
K51913145FC
T52396702FE
T52396782FD
K7114323738
T52396782FD

I’m using the S300TH temperature/humidity sensor in the working room for test purposes and got myself a FHT80TF-2 door/window sensor and a FHT8v electric valve controller as test devices.

Breadboard and test devices

I want to control the FHT8v directly from this server without the need to use the FHT80b device which is originally intended to steer the valve controller. Normally this should be straight forward but a first test was not successful. I will publish the results once I have it running.

Defective weather sensor

My weather sensor (OC-3) seems to be broken, humidity is constantly reported at 99%, as you can see here http://weather.appco.de . I checked Google for potential solutions and found someone who renewed some soldering points to get it working again.

I will send it back to the manufacturer to get it replaced as the sensor is still covered from the warranty.

Maybe this is a good chance to add a solar panel to get rid of the batteries.

Re-design of the HomeAutomation board

It turned out that the original layout of the HomeAutomation Board was far from perfect. From time to time I needed access to the USB hub to pull out or plug in an USB extension. This was almost impossible as the USB hub was located to far behind the wall. After fiddling around for quite some time I decided to give the whole board a re-design.

HomeAutomation Board

The key difference is now that the USB hub is the 1st item on the board when you try to access it. Which turns out to work perfectly. Especially as I will start my experiments on the Raspberry Pi with the CUL device which is during normal operations connected to the USB hub on the board.