Montag, 4. August 2014

Connecting BT Module HC-06 to MultiWii

Background/Problem: By default the HC-06 module chips with the baudrate/protocol set to 9600/8N1, whereas the MWC itself expects 115200/8N1. 0) Preparing Module You need a USB to seriell converter in order to send AT commands to the BT device to change the baudrate. For communication itself you can use minicom. Once you have a connection, send AT to check that the connection and protocol is setup correctly. Now, in order to change baudrate to 115200 you have to send AT+BAUD8 command. The problem is that the modem itself responds as soon as it sees AT with OK. The reason for that is that it expects the complete command in less than 1 second. One way to deal with that is to send this command as Modem init string from minicom. You can setup the init string in the minicom options. Later on, just press and to send the string. The modem will respond with OK115200. For more details see also

Dienstag, 1. April 2014

SALT/Subversion Backend

This post is about configuring SALT Stacks subversion backend. Salt itself provides some information on its website, but its not obvious how it works in detail. I'm running my salt-master on an Ubuntu 12.0.4 LTS version, the salt-master (at time of writing in version 2014.1.0-1precise1) package has been downloaded from Launchpad PPA.

In order to use subversion (or other version control backends), it is necessary to edit the salt masters configuration file - in /etc/salt/master. There are already some commented sections for gitfs_remotes, but none for mercurial or subversion. However, the principle behind the configuration/backends is the same. In the following we assume that our salt configuration space is hosted under http://svn.example.com/sourcecode/salt/. Below that directory we have a typical subversion project structure - that means trunk, branches, tags. Salt assumes that the base environment is below trunk, all other environments are derived from the subdirectories in branches and tags.


svnfs_remotes:  - https://svn.example.com/sourcecode/salt
svnfs_trunk:
  - trunk: trunk
svnfs_branches:
  - branches: branches
svnfs_tags:
  - tags: tags

After adding this to your salt masters configuration andy after restarting the daemon, you will most likely find the following error message in your salt error log file (/var/log/salt/master.log).

2014-04-01 12:56:39,007 [salt.loaded.int.fileserver.svnfs][ERROR   ] subversion fileserver backend is enabled in configuration but could not be loaded, is pysvn installed?
This can be solved by adding python-svn package (apt-get install python-svn).
That's it, the configuration space is now visible to your salt-minions.

Samstag, 22. März 2014

MultiWii AIOP Mega mit Fatshark Trinity V2.0 Headtracker und PPM-SUM Empfänger, FPV Servo/Gimbal Passthrough

In diesem Artikel beschreibe ich wie man MultiWii Version 2.3 so modifiziert das man die Servosignale für einen 3 Achsen Headtracker (FPV Brille Fatshark Attitude V2.0 mit Trinity Headtracker) über einen PPM-Sum Empfänger (z.B. Jeti Duplex RSat2) mit empfangen und dann auf an den Flightcontroller angeschlossene Servos durchschleifen kann.
Als FlightController muss z.B. ein Multiwii Mega bzw. Crius AIOP vorhanden sein - z.B. MegaPirate AIO Flight Controller (Atmega 2560) von Hobbyking. Nur ein Atmega 2560 hat genügend Ausgänge um neben den flugbetrieb auch zusätzlich noch genug externe Servos ansteuern zu können.

Den Headtracker der Fatshark Attitude habe ich über Lehrer Schüler Eingang in meine MC-22 von Graupner eingeschleift. Die Signale selbst lege ich dann im Gebermenü auf die Kanäle 10 (PAN), 11(TILT) und 12(ROLL), so das diese am RSat2 Empfänger auf den hinteren obersten Kanälen landen und ich trotzdem noch zusätzlich alle 4 Aux Kanäle nutzen kann. Mit diesem Setup haben wir das Signal schonmal prinzipiell auf den Flightcontroller - nun müssen wir jedoch noch die MultiWii Software so modifizieren das diese auch das Signal durchreicht. Auf  folgenden Link sehen wir das auf einen Mega mit aktivierten Hardware PWM folgende Anschlüsse als Servoausgänge genutzt werden können.
  • Servos HW_PWM : 44,45,46,11,12,6,7,8
Ich entscheide mich also die Ausgänge 44,45 und 46 zu benutzen, da diese bei mir ungenutzt sind und auf den Controller günstig liegen. Ich möchte also folgendes Mapping/Signalfluss erreichen.
  • Empfänger Kanal 10 -> Controller Ausgang 44 (PAN)
  • Empfänger Kanal 11 -> Controller Ausgang 45 (TILT)
  • Empfänger Kanal 12 -> Controller Ausgang 46 (ROLL)
Ebenfalls auf der MultiWii Wiki Seite können wir das interne MultiWii Servo Mapping ableiten.
  • Ausgang 44 -> Position 0, d.h., Servo[0]
  • Ausgang 45 -> Servo[1]
  • Ausgang 46 -> Servo[2]
Wir haben nun alle Informationen zusammengetragen um mit wenig Aufwand den Quellcode anzupassen. Als erstes stellen wir sicher das PPM-SUM richtig konfiguriert ist und funktioniert, es gibt hierzu genügend Informationen im Netz, deswegen gehe ich darauf nicht genauer ein. Als nächstes aktivieren wir
  •     #define MEGA_HW_PWM_SERVOS
und fügen ein neues define hinzu für unseren Headtracker hinzu.
  •     #define SERVO_HEADTRACKER
Nun machen wir die ersten Anpassungen in der Output.cpp. Entsprechend des ausgewählten Copters (bei mir VTAIL4) passen wir die Stelle mit dem elif defined(VTAIL4) folgendermassen an.
  #elif defined( VTAIL4 )
    motor[0] = PIDMIX(-8/10,+1, +1); //REAR_R
    motor[1] = PIDMIX(-1, -1, +0); //FRONT_R
    motor[2] = PIDMIX(+8/10,+1, -1); //REAR_L
    motor[3] = PIDMIX(+1, -1, -0); //FRONT_L
    //3-axis trinity headtracker
    servo[0] = rcData[9]; // PAN signal on ppm-sum channel 9
    servo[1] = rcData[10]; // TILT signal on ppm-sum channel 10
    servo[2] = rcData[11]; // ROLL signal on ppm-sum channel 11
  #elif defined( FLYING_WING )
Diese Anpassung sorgt dafür das die Servosignale welche in rcData bereitliegen auf die Servoausgänge servo[0-2] gemapped werden. Nun sorgen wir noch dafür das unsere Servosignale auch verarbeitet/ausgegeben werden, hierfür muss u.a. #define SERVO gesetzt sein (def.h). Um dies zu erreichen habe ich mich entschieden folgende Stelle anzupassen.
#if defined(COPTER_WITH_SERVO) || defined(SERVO_TILT) || defined(GIMBAL) || defined(CAMTRIG) || defined(SERVO_MIX_TILT)
  #define SERVO
#endif
Wir erweitern dieses define um unseren Headtracker define switch.
#if defined(COPTER_WITH_SERVO) || defined(SERVO_TILT) || defined(GIMBAL) || defined(CAMTRIG) || defined(SERVO_MIX_TILT) || defined(SERVO_HEADTRACKER)
  #define SERVO
#endif
Nun müssen wir nur noch an einer Stelle dafür sorgen das auch ein entsprechendes internes Servo Mapping realisiert wird, dies erreichen wir über folgende Anpassung.
#if (defined(SERVO_TILT)|| defined(SERVO_MIX_TILT))&& defined(CAMTRIG)
  #define SEC_SERVO_FROM   1 // use servo from 1 to 3
  #define SEC_SERVO_TO     3
#else
Diesen Teil erweitern wir ebenfalls mit unseren define SERVO_HEADTRACKER...
#if (defined(SERVO_TILT)|| defined(SERVO_MIX_TILT))&& defined(CAMTRIG) || defined(SERVO_HEADTRACKER)
  #define SEC_SERVO_FROM   1 // use servo from 1 to 3
  #define SEC_SERVO_TO     3
#else

Wir sind nun in der Lage unsere Kamera gesteuert durch einen Headtracker über das PPM-SUM Signal am Flightcontroller zu betreiben.

Quellen:
  • http://www.hobbyking.com/hobbyking/store/uploads/684736734X7478X34.pdf
  • http://www.rctimer.com/download/Crius_AIOP_Manual_MWC.pdf 
  • https://wiki.fs-et.de/student-lab/MC22s

Donnerstag, 20. März 2014

RCTimer Voltage & Current Sensor 90A (suit MultiWii, APM, etc) mit Multiwii and Megapirate AIO Flight Controller w/FTDI (ATmega 2560) V2.0

In diesem Post geht es um den Anschluss  und der Konfiguration des Spannungs und Strom Sensor 90 Ampere von RCTimer an eine MegaPirate AIO Flight Controller (Atmega 2560) von Hobbyking mit der MultiWii Version 2.3.

Im folgenden installieren/verbinden wir die Hardware und kümmern uns dann um die Softwarekonfiguration. Die Boards CRIUS AIO Pro V1.0 und MultiWii Mega legen die Anschlüsse/Pins A0,A1,..,A3, usw. auf den entsprechend markierten Socket A0..A5(A8) am Controller. Wir können unseren Strom und Spannungs Sensor also direkt mit diesen Anschluss verbinden. Per Default erwartet MultiWii (Version 2.3) den Stromsensor auf A2 und den Spannungssensor auf A3 (siehe Foto).

Das Softwaresetup erfolgt in den folgenden Schritten:
  1. Löschen des EEPROM auf den Controller
    • Ardunio->Beispiele->EEPROM->eeprom_clear
    • Programm kompilieren und uploaden
    • (Das Löschen ist notwendig damit die neuen Werte auch korrekt übernommen werden)
  2. Anpassen der MultiWii Konfiguration - config.h
    • Aktivieren von #define POWERMETER_HARD
    • Setzen von #define PSENSORNULL auf 0
    • Setzen von #define PINT2mA auf 132, lt. Datenblatt müsste dieser Wert korrekt sein
  3. Hochladen des Programms auf den Controller
Nun kann man prüfen ob der Controller korrekt konfiguriert ist, d.h. die Messwerte stimmen. Hierfür einen absolut vollgeladenen Akku anschliessen und anschliessend fliegen gehen und nach dem Fliegen über die GUI den Powerwert auslesen und notieren. Jetzt einfach den Akku laden und prüfen ob die nachgeladene Kapazität mit der entnommenen identisch sind. Falls nicht, dann kann man über folgende Formel eine Anpassung/Finetuning vornehmen.
PINT2mA (neu) = PINT2mA (alt) * Ladegerät_Kapazität / GUI_Kapazität.
PINT2mA nun einfach nach oben beschriebenen Muster updaten.


TIP: Falls man seinen Sensor debuggen will, so kann man im Multiwii Code die Sensorwerte/Zwischenwerte und auch Parameter auf die Debugsensoren in der GUI legen. Hierzu muss man in der Multiwii.cpp nach POWERMETER_HARD suchen und dort unter case 0: (hier wird der Powersensor gelesen), z.B. debug[0] = p; aktivieren. Analog kann man dann auch mit debug[1], usw., die Werte powerValue, conf.psensornull, conf.pint2ma ausgeben.

Btw. Multiwii hat auch einen Tuningguide für den Powersensor - hier zu finden.




Viel Spass :)

Montag, 20. Januar 2014

Jeti R10 mit Sat1 & Sat2 PPM/Sum Signal Out Problem

Als Fernsteuerungssystem für meine Multicopter habe ich mich für das Jeti System entschieden da dieses System sehr gut in meine ältere Graupner Anlage integrierbar ist. Einige Jeti Empfänger bieten auch ein interessantes Feature - nämlich die Ausgabe des PPM Signals ohne/mit geringer Vorverarbeitung. Dieses PPM Signal kann demzufolge über nur eine Signalleitung in diverse Flightcontroller (Multiwii, KK2, usw.) eingespeist werden (sogenanntes PPM Sum Signal). Jeti bietet zum Beispiel RSat2 Empfänger, diese haben nur einen Ausgangskanal (PPM).
Die RSat2 funktionieren zum Beispiel ohne Probleme an einer Multiwii. Wenn man allerdings eine Anlage mit 12 oder mehr Kanälen hat und zusätzlich einen Multicopter mit z.B. Kamera (Gimbal), Fotoanlage, usw. direkt über die Fernsteueranlage steuern will, dann kann man dies zumindest theoretisch über die grösseren Empfänger (ab R10). Diese Empfänger bieten neben den normalen Servoausgängen (z.B. 10 Stück), weitere Satellitenausgänge (2 Stück). Ich habe mir einen solchen R10 gekauft und den Sat2 auf PPM Out geschalten, während die normalen Servokanäle noch aktiv waren. Leider ist das so generierte PPM Signal für eine Multiwii nicht zu gebrauchen, da es scheinbar zu Verzerrungen oder Überlagerungen kommt. Auch ein deaktivieren der Servokanäle konnte dieses Problem nicht lösen. Schlussendlich scheint mir nur die Lösung mit Doppelempfänger zu bleiben, einen RSat2 für das PPM Signal an die Multiwii und einen weiteren kleinen R5/R6/R7 für weitere Zusatzfunktionen. Nach meinen Recherchen bin ich leider nicht der einzige welcher sich mit der beworbenen Funktionalität diesen Empfänger gekauft hatte und dann im Nachgang festgestellt hat das dies so leider nicht funktioniert. Ich werde mal Jeti bzgl. des Problems kontaktieren.

m2c

Dienstag, 24. Dezember 2013

On the way to deterministic binariy (gcc) output

In some projects (actually it should be in general) it is necessary to prove that two releases from the same input (source + configuration) generate the same output. This property is useful because it allows one to compare the binary output of a compilation/linking step. If there is no difference at all, one can be sure that there was no change on source code either and that the behaviour of the software doesn't change (as long as one trusts the compiler). It also allows one to prove that changes in the build infrastructure/system doesn't change the output of a build, that an archiving concept works, etc.

There are several aspects that should be considered on the way to deterministic binary output:
  1. absolute paths which are compiled into the binary code (mainly for debugging)
  2. compiler sometimes decide randomly e.g., which optimization to use, which path to choose, or how to mangle a specific function in anonymous namespaces. Of course, this has no influence on the functional properties of the code, the binaries are (they should ;-) ) always be functional equivalent.
  3. timestamps, uuid in object files, libraries, etc.
  4. timestamps, dates generated by __DATE__, __TIME__, __TIMESTAMP__ macros

An example where the first point comes into play is the __FILE__ macro which is often used for debugging purposes. The implementation of how this macro gets expanded depends from compiler to compiler. For example Microsofts C++ Compiler uses an FC flag which allows to control if the macro expansion to absolute or relative paths. Of course, the question regarding absolute or relative paths is only of value if you have multiple build machines with different location of workspaces or you care about information of your workspace that gets delivered to your customer. You can easily check if there are any path informations like that in the binary by searching for the workspace path in the binary.

strings binary.out | grep workspace

If there is any output that contains full paths to your sourcecode files then you would have to take care of this problem. For me, I have discovered two solutions:
  • Using compiler switches to make sure that paths are relative
  • Making sure that the build environment/workspaces are on the same absolute paths independent of the actual build machine(master, slave jenkins)
The next point is quite interesting. The average programmer would expect that given a specific piece of code and a set of rules for the compiler and linker, the outcome would be always the same. Well this is (normally) true for the functional behaviour of the piece of code. However, this is not true when comparing the two binaries on byte level. You can easily compare two binaries by using the


cmp -b -l b1 b2
 
This will show you all binary differences with location and difference for b1 vs. b2.
The binary incompatibility has several reasons: one is for examples how gcc mangles functions in anonymous namespaces. A part of this name mangling is randomized by using a random generator. If you have taken care of our first point and your object files still differ, then you can use a special gcc parameter. The -frandom-seed=<string> allows one to specify a string which will be used to initialize the random generator. The documentation for this option tells us...

       -frandom-seed=string
           This option provides a seed that GCC uses when it would otherwise
           use random numbers.  It is used to generate certain symbol names
           that have to be different in every compiled file.  It is also used
           to place unique stamps in coverage data files and the object files
           that produce them.  You can use the -frandom-seed option to produce
           reproducibly identical object files.

           The string should be different for every file you compile.

That means that we have to provide random strings for each file we will compile. I have found one solution to this problem in this blogpost by Jörg Förstner. He suggested to use the md5 hash of the source file as input to the -frandom-seed. This is sufficient as it will change for different source files and vice versa will provide the same seed if the source hasn't changed. He suggested to use the following compile parameters...

           $(CC) -frandom-seed=$(shell md5sum $< | sed 's/\(.*\) .*/\1/') $(CCFLAGS) -c $< -o $@

The seed is constructed by calculating the md5sum of the source code file (e.g. test.cpp).

          md5sum $<
          b61f78373a5b404a027c533b9ca6280f  test.cpp

This result is piped into sed (sed 's/\(.*\) .*/\1/') to cut away the filename part behind the actual md5 sum.

The problem described by the third point (timestamps, uuids) is created by some linkers in the linking step. For example when building object files/static libraries/archives with the ar tool, ar will also insert timestamps, uuids and other stuff which will change from build to build. You can easily try this out by executing ar two times and comparing by comparing the generated output. However, for the ar tool there is a simple solution to this problem, ar comes with the -D option which will turn ar into deterministic mode. The documentation for -D tells us...

       D   Operate in deterministic mode.  When adding files and the archive
           index use zero for UIDs, GIDs, timestamps, and use consistent file
           modes for all files.  When this option is used, if ar is used with
           identical options and identical input files, multiple runs will
           create identical output files regardless of the input files'
           owners, groups, file modes, or modification times. 

My command line for building a static library looks like:
      ar Drvs <output> <input> 

In some cases, for example when using a cross-compiler tool chain, you cannot easily change the bin-utils version to get an ar version that supports the deterministic option. This was the motivation for someone to write a tool that wipes out the timestamps in the generated archive files. You can find this tool at github under the following url: https://github.com/nh2/ar-timestamp-wiper/tree/master. If you use cmake as part of your build system, you can link in the tool in the finish step of the archive generation.
          SET(CMAKE_C_ARCHIVE_FINISH "ar-timestamp-wiper ")
          SET(CMAKE_CXX_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH})
          SET(CMAKE_C_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH})   

The last point (timestamps, dates introduced by macros like __DATE__, __TIME__, __TIMESTAMP__) can addressed by specifying a deterministic/known value for the corresponding build. I know at least two ways how to do this, both work in general, but sometimes one approach is easier to use then the other.
  1. faketime/libfaketime
  2. overriding the macros by compiler defines  
The first approach works by calling the build step/executable using faketime. Faketime then uses the LD_PRELOAD mechanism to override some of the syscalls to pretend a specific time.
          apt-get install faketime
          faketime '2014-01-09 00:00:00' /usr/bin/date
The second approach works by adding for example -D__DATE__="'Jan 9 2014'" -D__TIME__="'12:00:00'" to your buildstep. You have to take care that that you specify a valid date and time according to the expected return values of __DATE__ and __TIME__.

 References:

  • http://cmake.3232098.n2.nabble.com/How-to-calculate-a-value-quot-on-the-fly-quot-for-use-with-gcc-compiler-option-td3277077.html
  • http://stackoverflow.com/questions/14653874/deterministic-binary-output-with-g
  • https://wiki.debian.org/ReproducibleBuilds

Freitag, 13. Dezember 2013

KVM networking with guests having static public ip addresses

In this blogpost I will show you how to setup kvm networking in the way that guest IPs are mapped to the local network. This way it is possible have guests running on the host with external/public IP addresses. At first kvm should be already installed, additionally we should check if bridge-utils is already installed.
 
sudo apt-get install bridge-utils

Assuming the following scenario:
  • host system ip configuration:
    •   IP: 10.10.10.5
    • netmask: 255.255.0.0
    • Gateway: 10.10.0.1
    • DNS: 10.10.0.250, 10.10.0.251
  • guest ip configuration:
    • IP: 10.10.10.10
    • netmask: 255.255.0.0
    • Gateway: 10.10.0.1
    • DNS: 10.10.0.250, 10.10.0.251
We have to edit /etc/network/interfaces to enable the bridges. Currently my interfaces file looks like that:

auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
       address 10.10.10.5
       netmask 255.255.0.0
       gateway 10.10.0.1
       dns-nameservers 10.10.0.250 10.10.0.251 


This has to be changed in the following way:
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
       address 10.10.10.5
       netmask 255.255.0.0
       gateway 10.10.0.1
       dns-nameservers 10.10.0.250 10.10.0.251 
       bridge_ports eth0
       bridge_stp off
       bridge_fd 0
       bridge_maxwait 0
Now we have to restart networking to incorporate the changes.
/etc/init.d/networking restart

After that we can run vmbuilder to create a new machine with the corresponding client ip configuration.
vmbuilder kvm ubuntu --suite=precise --flavour=virtual --arch=amd64 
--install-mirror=http://apt-cacher-ng:3142/ubuntu -o --libvirt=qemu:///system 
--ip=10.10.10.10 --gw=10.10.10.1 --part=vmbuilder.partition  --templates=templates/ 
--user=admin --name=admin --pass=pass --addpkg=acpid 
--firstboot=/opt/kvm/images/vslave-001/vmbuilder.boot.sh 
--mem=4096 --hostname=build-vslave-001 --bridge=br0 


  • https://help.ubuntu.com/community/KVM/Networking
  • http://docwiki.cisco.com/wiki/OpenStack:VM_Build
  • http://foswiki.org/Support/UbuntuVmBuilder
  • http://www.fak-online.net/?p=22
  • http://www.linux-kvm.org/page/Networking
  • http://blog.braastad.org/?p=128
  • http://www.howtoforge.com/virtualization-with-kvm-on-ubuntu-12.04-lts