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.


use Device::BCM2835;
use strict;

# call set_debug(1) to do a non-destructive test on non-RPi hardware
# Device::BCM2835::set_debug(1);
|| 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.