Latest Entries »

To get the necesary Temperature Information i used several DS18S20 and a OneWire to USB Adapter.

As i want to use several Scripts to work with the same Temperature Data i wrote a small Deamon to get the Temperature Data via digitemp and save it in “sensor” files under /tmp/sensorN. OneWire Fs only gave wrong Temperature Data (85°C) and the nodejs script got some serious problems with digitemp.

NOTE: I created two UDEV rules to get a “static” path for the two serial devices(Outlet and 1Wire Adapter)

cat /etc/udev/rules.d/44-ttyusb.rules
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A6XDT7AO", SYMLINK+="steckdose", ACTION=="add"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="ea90", ATTRS{serial}=="10TK4WX6", SYMLINK+="onewire", ACTION=="add"

At first you need to initialize your digitemp config file:

digitemp -i -s /dev/onewire -c /etc/digitemp.conf 

The next step is to create the Daemon under /usr/local/bin/onewire/onewire.pl:

#!/usr/bin/perl

use strict;
use warnings;

use Proc::Daemon;
use Proc::PID::File;

MAIN:
{
	# Daemonize
	Proc::Daemon::Init;

	# If already running, then exit
	if (Proc::PID::File->running()) {
		exit(0);
	}

	my $continue = 1;
	$SIG{TERM} = sub { $continue = 0 };
	
	my $temperature;
	my $c = 0;
	my $sensor_count = 0;
	
	# Get Sensor #
	open DIGITEMPCONF, "<", '/etc/digitemp.conf' || die "Can't open /etc/digitemp.conf: $!";
	while() {
	        if($_ =~ m/SENSORS/) {
	                my @tmp = split(' ',$_);
	                $sensor_count = $tmp[1];
	        }
	}
	
	# filling sensor files arra<
	my @sensorfiles;
	
	for(my $i = 0; $i ", $sensorfile || die "Can't open $sensorfile: $!";
			$temperature = 85;
			while ($temperature == 	85) {
				$temperature = `/usr/bin/digitemp -c /etc/digitemp.conf -t$c -q -o"%.2C" -r1000`;
			}
			print $temp_sensorfile $temperature;
			print $temperature;
			close $temp_sensorfile;
			$c++;
		}
		$c = 0;
		sleep(15);
	}
	close DIGITEMPCONF;
}

And a start stop script under /etc/init.d/onewire (install it with update-rc.d onewire defaults)

#!/bin/sh
### BEGIN INIT INFO
# Provides:          onewire
# Required-Start:    
# Required-Stop:
# Should-Start:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6 
# Short-Description: Starts the onewire "daemon" to provide onewire sensor datat under /tmp/sensorN
# Description: Starts the onewire "daemon" to provide onewire sensor datat under /tmp/sensorN       
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
. /lib/init/vars.sh

do_start () {
	/usr/local/bin/onewire/onewire.pl
}

do_status () {
	if [ -f /var/run/onewire.pl.pid ] ; then
		echo "onewire is running";
		return 0
	else
		echo "onewire is not running";
		return 4
	fi
}
do_stop () {
	killall onewire.pl
}

case "$1" in
  start|"")
	do_start
	;;
  restart|reload|force-reload)
	do_stop
	rm /tmp/sensor*
	do_start
	;;
  stop)
	do_stop
	;;
  status)
	do_status
	exit $?
	;;
  *)
	echo "Usage: onewire [start|stop|status]" >&2
	exit 3
	;;
esac

:

After a lovely /etc/init.d/onewire restart you go the sensor data for each sensor under /tmp/sensorN
for example:

cat /tmp/sensor0
24.19

The sensor data will be updated every 15 seconds and the N in the sensor file is the same number you can find in the digitemp config (/etc/digitemp.conf).

Since my actual Terrarium Controller got serious problems with the usb power strip, I bought a raspberry pi and a Ninja Pi Crust to update the old System.

The old System contains of the following Elements:
- 1Wire Temperature Sensor
- USB Power Strip (sispm)
- WebInterface
- Many Shell Scripts to switch outlets on/off
- Big Crontab…

The new System should consist of the following Elements:
- 1Wire Temperature Senso
- Power Strip based on some very cheap replaceable components like arduino, releay modules
- reworked Terrarium Conroll Scripts based on Perl without big crontab…
- Fancy webinterface with graphs and buttons
- Maybe controlling some more items ;)

As power strip I used a 4 Port relay in combination with some “Aufputz” Power sockets and a Arduino Pro mini.

outlet_1
I connected the four relay Ports to the Arduino, disabled the Auto reset and uploaded the following Code:

 
//#define DEBUG

int CH1 = 9;
int CH2 = 12; 
int CH3 = 11; 
int CH4 = 10; 

String Input;
int ch1Value = 0;
int ch2Value = 0;
int ch3Value = 0;
int ch4Value = 0;
int ChSelected = 0;
int ChValue = 0;

void setup()
{
  pinMode(CH1, OUTPUT);      // sets the digital pin as output
  digitalWrite(CH1, HIGH); 
  pinMode(CH2, OUTPUT);      // sets the digital pin as output
  digitalWrite(CH2, HIGH);
  pinMode(CH3, OUTPUT);      // sets the digital pin as output
  digitalWrite(CH3, HIGH);  
  pinMode(CH4, OUTPUT);      // sets the digital pin as output
  digitalWrite(CH4, HIGH); 
        
       
     
    
  Serial.begin(9600);
  #ifdef DEBUG
    Serial.println("DEBUG!!!");
    Serial.println("Started");
  #endif
}

void loop()
{
  while (Serial.available()) 
  {
    delay(3);  //delay to allow buffer to fill 
    if (Serial.available() >0) 
    {
      char c = Serial.read();  //gets one byte from serial buffer
      if(c  != ';')
      {
        Input += c; //makes the string readString
      }
      else
      {
        ParseInput();
      }

    } 
  }

}

void ParseInput()
{
  //10;
  //Define single Channels
  if (Input.length() == 2) 
  {
#ifdef DEBUG
    Serial.print("Got: ");
    Serial.println(Input); 
#endif
ChSelected = Input.substring(0,1).toInt();
ChValue = Input.substring(1,2).toInt();
#ifdef DEBUG
    Serial.print("Selected Channel: ");
    Serial.println(ChSelected); 
    Serial.print("Value: ");
    Serial.println(ChValue); 
#endif
// Set:1,1
Serial.print("Set:");
    switch (ChSelected) 
    {
      case 1:
        #ifdef DEBUG
        Serial.print("Case 1 ");
        #endif      
        digitalWrite(CH1, !ChValue);
        ch1Value = ChValue;
        Serial.print("1,");
        Serial.print(ChValue);
      break;
      case 2:
        #ifdef DEBUG
        Serial.print("Case 2 ");
        #endif 
        digitalWrite(CH2, !ChValue);
        ch2Value = ChValue;
        Serial.print("2,");
        Serial.print(ChValue);
      break;
      case 3:
        #ifdef DEBUG
        Serial.print("Case 3 ");
        #endif 
        digitalWrite(CH3, !ChValue);
        ch3Value = ChValue;
        Serial.print("3,");
        Serial.print(ChValue);   
      break;
      case 4:
        #ifdef DEBUG
        Serial.print("Case 4 ");
        #endif 
        digitalWrite(CH4, !ChValue);
        ch4Value = ChValue;
        Serial.print("4,");
        Serial.print(ChValue);  
      break;
    }
    Serial.println(";");
     Input="";
  } 
  //1; 
  //Status for Channel
  else if (Input.length() == 1)
  {
    ChSelected=Input.toInt();
    #ifdef DEBUG
    Serial.print("Got status request for: ");
    Serial.print(ChSelected); 
    #endif
    //Status:1,1
    Serial.print("Status:");
    switch (ChSelected) 
    {
      case 1:
        #ifdef DEBUG
        Serial.print("Case 1 ");
        #endif
        Serial.print("1,");      
        Serial.print(!digitalRead(CH1));
      break;
      case 2:
        #ifdef DEBUG
        Serial.print("Case 2 ");
        #endif
        Serial.print("2,");    
        Serial.print(!digitalRead(CH2));
      break;
      case 3:
        #ifdef DEBUG
        Serial.print("Case 3 ");
        #endif
        Serial.print("3,");    
        Serial.print(!digitalRead(CH3));
      break;
      case 4:
        #ifdef DEBUG
        Serial.print("Case 4 ");
        #endif 
        Serial.print("4,");   
        Serial.print(!digitalRead(CH4));
      break;
    }
    Serial.println(";");
    Input="";
    
  }
  //10,20,30,41;
  //Define all Channels
  else if (Input.length() == 11)
  {
    #ifdef DEBUG
    Serial.print("Got; ");
    Serial.println(Input);
    #endif
    ch1Value=Input.substring(1,2).toInt();
    ch2Value=Input.substring(4,5).toInt();
    ch3Value=Input.substring(7,8).toInt();
    ch4Value=Input.substring(10,11).toInt();

    #ifdef DEBUG
    Serial.print("ch1Value: ");
    Serial.println(ch1Value);
    Serial.print("ch2Value: ");
    Serial.println(ch2Value);
    Serial.print("ch3Value: ");
    Serial.println(ch3Value);
    Serial.print("ch4Value: ");
    Serial.println(ch4Value);
    #endif    
    digitalWrite(CH1, !ch1Value); 
    digitalWrite(CH2, !ch2Value);   
    digitalWrite(CH3, !ch3Value);   
    digitalWrite(CH4, !ch4Value); 
    Input="";
  }
 Input="";
}

The next step was to connect a 5V FTDI Adapter to the Arduino and place everything in the “Aufputz” case.
Now you have a usb controlled outlet ;)

Switch outlet on/off:
Command:$Outlet,$State(0,1);
Returns: Set:$Outlet,$Status
Example:

 
1,0;
Set:1,0
1,1;
Set:1,1

Get Status of Outlet:
Command:$Outlet
Returns: Status:$Outlet,$Status
Example:

 
1;
Status:1,1

Hi,
if you receive the following Messages while restarting the NinjaBlock Service (stopninja && startninja)

/sys/devices/virtual/gpio/gpio23/value: No such file or directory

or

[System] Sun Jan  5 01:17:07 EST 2014 Flashing Arduino...Pass 1 Failed!
avrdude: stk500_getsync(): not in sync: resp=0xe0

or

`/sys/devices/virtual/gpio/gpio23/*': No such file or directory

Maybe your GPIO Pins are not exported any more…
The following command resolves the issues for me:

echo 23 > /sys/class/gpio/export

Windows Azure uses the DHCP Protocol to assign IP Addresses. To ensure that a Server always receive the same IP the IP has to be reserved.

In Azure the IP will not be setup fixed on the target Server but rather a reservation in DHCP will be created.

This can be archived with the following PowerShell Script:

Note: This requires a Public Setting file. The necessary Steps are described here.

 

 
# DAFES
$modulePath = "C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\Azure.psd1"
Import-Module $modulePath
$VerbosePreference="Continue"
$PublishSettings = "C:\PUBLISHSETTINGSFILE.publishsettings"
cd c:\
Import-AzurePublishSettingsFile $PublishSettings
$SubscriptionName = "SUBSCRIPTIONNAME" # DEFINE Subscription HERE

Select-AzureSubscription -SubscriptionName $SubscriptionName


Write-Host "Get Azure VMs"
$AzureVMs = $(Get-AzureVM)

foreach($AzureVM in $AzureVMs)
{
    Write-Host "Got $($AzureVM.Name) in Service $($AzureVM.ServiceName)"
    if(!$(Get-AzureVM -ServiceName $($AzureVM.ServiceName) -Name $($AzureVM.Name) | Get-AzureStaticVNetIP) )
    {
        Write-Host "VM $($AzureVM.Name) has no static IP"
        $IP = $(Get-AzureVM -ServiceName $($AzureVM.ServiceName) -Name $($AzureVM.Name)).IpAddress
        Write-Host "VM $($AzureVM.Name) has the following dynamic IP: $IP"        
        Write-Host "VM $($AzureVM.Name) set to $IP"
        Get-AzureVM -ServiceName $($AzureVM.ServiceName) -Name $($AzureVM.Name)|Set-AzureStaticVNetIP -IPAddress $IP| Update-AzureVM
        $StaticIP = $(Get-AzureVM -ServiceName $($AzureVM.ServiceName) -Name $($AzureVM.Name) | Get-AzureStaticVNetIP).IPAddress
        Write-host "VM $($AzureVM.Name) was set to the following IP:  $StaticIP"
    }
    else
    {
        $StaticIP = $(Get-AzureVM -ServiceName $($AzureVM.ServiceName) -Name $($AzureVM.Name) | Get-AzureStaticVNetIP).IPAddress
        Write-host "VM $($AzureVM.Name) has already the following static IP: $StaticIP"
    }
    
}

As always no guarantee ;)

I’ve merged some Libraries to create an small Naza to FrSky telemetry adapter.

You can find the Code here.

It get´s the GPS Data like Position and Speed and converts these information to the FrSky S.Port Protocol.

I’ve tested it with Naza V2 and it’s based on the Teensy 3.1.

IMG-20140411-WA0002

Air

Y6

20140308-Y6_005

  • Naza M V2 + GPS
  • IOSD mini with 3 Video Switch from HK and TBS GOPRO LINK BOARD
  • NTM Prop Drive Series 28-30A 750kv / 140w
  • HobbyKing 20A BlueSeries Brushless Speed Controller Flashed with SimonK
  • 2 x SLS XTRON 4000mAh 2S1P 7,4V 20C/40C

Ground

RC
FrSky Taranis mit X8R und D4R-II
Short Range
FarShark DOMINATOR mit TBS DOMINATOR RX (5G8) (32Kanal)

DX6i Gimbals in T9x

As I was not very satisfied with the Gimbals from my T9x I used the one from my Spektrum DX6i.

To do so i needed to modify the DX Gimbals a litle bit (remove the “Screw Towers”)
20131230_170443

The next steps are soldering the Gimbal wires together.
In my case I had the following wire combination:

  • Yellow/Orange(DX6i) to White(T9x)
  • Red(DX6i) to Black(T9x)
  • Black(DX6i) to Red(T9x)
  • 20131230_165839
    20131230_165857
    20131230_170622

    As the last Package available for Rasbian got some “small problems” regarding
    ykclient return value (106): Server response signature was invalid (BAD_SERVER_SIGNATURE)
    it is necessary to build it by your own untill the packages are updated.

    1. Install tools

    apt-get install autoconf libtool automake make libcurl4-gnutls-dev libykclient3 libusb-1.0-0-dev libpam-dev
    

    2. Create Temp Folder for git clones

    mkdir /root/temp

    3. Build YubiKey C Library

    cd /root/temp/apt
    git clone git://github.com/Yubico/yubico-c.git
    cd /root/temp/yubico-c
    autoreconf --install 
    ./configure && make check && make install
    

    4. Build yubico-c-client

    cd /root/temp/
    git clone git://github.com/Yubico/yubico-c-client.git
    cd /root/temp/yubico-c-client
    autoreconf --install 
    ./configure && make check && make install
    

    5. Build yubikey-personalization

    cd /root/temp/
    git clone git://github.com/Yubico/yubikey-personalization.git
    cd /root/temp/yubikey-personalization
    git submodule init
    git submodule update
    autoreconf --install
    ./configure && make check && make install
    

    6. Build yubico-pam

    cd /root/temp/
    git clone git://github.com/Yubico/yubico-pam.git
    cd /root/temp/yubico-pam
    autoreconf --install
    ./configure && make check && make install
    

    7. Get the first 12 Chars

    read -p "Enter OTP: " s && echo ${s:0:12}

    8. Get Yubikey API Key and ID

    9. Create “THE MASTER FILE”

    mkdir /etc/yubikey_mappings/
    vim /etc/yubikey_mappings/authorized_yubikeys
    

    Enter the desired username with the 12char from Step 7
    Example: mustermann:dwjdwakdjkaw

    10. Edit /etc/pam.d/sshd to include the Yubikey Modul:

    vim  /etc/pam.d/sshd
    

    Insert the following line at the beginning. (Replace the Values from the Api ID and Key from Step 8

     auth required /usr/local/lib/security/pam_yubico.so id=nnnnn key=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk authfile=/etc/yubikey_mappings/authorized_yubikeys debug
    

    11. Modify /etc/ssh/sshd_config to include the follwing:

    # Change to yes to enable challenge-response passwords (beware issues with
    # some PAM modules and threads)
    ChallengeResponseAuthentication no
    
    # Change to no to disable tunnelled clear text passwords
    PasswordAuthentication yes
    

    12. Append the folling at the end of the line containing pam_unix.so in /etc/pam.d/common-auth

    try_first_pass
    

    Example:

    auth    [success=2 default=ignore]      pam_unix.so nullok_secure try_first_pass
    

    13. DEBUG DEBUG
    In case you want to see something:

    touch /var/run/pam-debug.log
    chmod go+w /var/run/pam-debug.log
    

    14. Restart SSH and Test

    /etc/init.d/ssh restart
    

    Login in while viewing the /var/run/pam-debug.log
    You need to enter your password and before hitting enter use the yubikey to generate the otp and login.

    Thanks to:

    https://v00d00.co/2013/08/10/yubikey-ssh-2-factor-authentication-with-ubuntu-13-04/

    After installing the Crazyflie Headless Client on my RPI as described here. I noticed that the YAW axis was mapped on the right shoulderbutton but it was impossible to use it.

    Below you can find a config which maps it back to the right stick.

    {
      "inputconfig": {
        "inputdevice": {
          "updateperiod": 10, 
          "name": "xbox360_mode1", 
          "axis": [
            {
              "scale": -1.0, 
              "type": "Input.AXIS", 
              "name": "thrust", 
              "key": "thrust", 
              "id": 3
            }, 
            {
              "scale": 1.0, 
              "type": "Input.AXIS", 
              "name": "yaw", 
              "key": "yaw", 
              "id": 5
            }, 
            {
              "scale": 1.0, 
              "type": "Input.AXIS", 
              "name": "roll", 
              "key": "roll", 
              "id": 0
            }, 
            {
              "scale": -1.0, 
              "type": "Input.AXIS", 
              "name": "pitch", 
              "key": "pitch", 
              "id": 1
            }, 
            {
              "scale": -1.0, 
              "type": "Input.BUTTON", 
              "id": 0, 
              "key": "pitchcal", 
              "name": "pitchNeg"
            }, 
            {
              "scale": 1.0, 
              "type": "Input.BUTTON", 
              "id": 3, 
              "key": "pitchcal", 
              "name": "pitchPos"
            }, 
            {
              "scale": 1.0, 
              "type": "Input.BUTTON", 
              "id": 7, 
              "key": "estop", 
              "name": "killswitch"
            }, 
            {
              "scale": -1.0, 
              "type": "Input.BUTTON", 
              "id": 2, 
              "key": "rollcal", 
              "name": "rollNeg"
            }, 
            {
              "scale": 1.0, 
              "type": "Input.BUTTON", 
              "id": 1, 
              "key": "rollcal", 
              "name": "rollPos"
            }, 
            {
              "scale": 1.0, 
              "type": "Input.BUTTON", 
              "id": 6, 
              "key": "exit", 
              "name": "exitapp"
            }
          ]
        }
      }
    }
    

    Move the original xbox360_mode1.json to xbox360_mode1.json.orig and create a new one with the content from here.

    Note:
    The config file can be found in: $INSDIR/crazyflie-pc-client/lib/cfclient/configs/input
    for example:

    /home/bitcraze/projects/crazyflie-pc-client/lib/cfclient/configs/input

    The right command for activating the Xbox Controller is:

    echo xbox360_mode1 > /home/bitcraze/controller.conf
    Follow

    Get every new post delivered to your Inbox.