AdSense

Monday 24 June 2013

Quadrocopter - first measurement of lift force

(Deutsche Version) Today, I measured the lift force with a motor from ebay and propellor. I used this motor (the price was 9,75) and this control unit. The propellor is a 10x4.5 propellor. The result: 238 g lift force.

The specifications of the motor are: 1200 kV, 25 A max, 18 A continuous. The specifications of the control unit are: 25 A max, 20 A continuous. This should provide some kind of general idea of how much lift force is possible with which equipment.

The measurement is the following: The motor is mounted on a frame of Lego and this frame is glued to a scale. The speed of the motor is set via an ATMega (see ), with a potentiometer connected to an analog input. The ATMega sets the speed depending on the measured value of the potentiometer. The measurement setup is the following:

Sunday 23 June 2013

SPI communication between ATMega and Raspberry PI

(Deutsche Version) I measure the temperature in my room (see ATMega - ATMega - Temperature measurement with the DS18S2). The temperature is read by an ATMega. This data is sent via SPI (see ATMega - Hardware SPI) to the Raspberry PI which collects the data and creates a plot. The missing part in the chain is the communication between ATMega and Raspberry PI. After some time of research, I found a good implementation of SPI on the Raspberry PI (http://www.airspayce.com/mikem/bcm2835/) called bcm2835. The code on the Raspberry PI is the following:

#include <bcm2835.h>
int main (int atgc, char** argv)
{
  if (!bcm2835_init())
  {
    return 1;
  }
  bcm2835_spi_begin();
  bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
  bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
  //CLOCK_DIVIDER: more information is provided here
  bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536);
  bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
  bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);

  //An example which sends a byte and then receives a byte
  char sendBits = 0b11111111;
  char returnBits = 0;

  while(true)
  {
    bcm2835_spi_transfer(sendBits);

    //send dummy bytes for receiving
    returnBits = bcm2835_spi_transfer(0);

  }
}


The code on the ATMega is the following (the three SPI functions explained in ATmega - Hardware-SPI have to be present in the program):

#include <avr/io.h>
int main()
{
  SPI_SlaveInit();
  char returnBits = 0;
  char sendBits = 0b11111111;
  while(true)
  {
    data = SPI_SlaveReceive();
    SPI_SlaveSend(sendBits);
  }
}

Wednesday 19 June 2013

C# - dot or comma problem

(Deutsche Version) In C, it was very simple: Every number has to be put in with a dot. Every programmer was aware of this. Sadly, C# thinks to be intelligent and (depending of the region) accepts a comma instead of a dot. On my german computer it looks like this:

string stringGerman = "3,1415926";
string stringEnglish = "3.1415926";
double doubleGerman = Convert.ToDouble(stringGerman);
double doubleEnglish = Convert.ToDouble(stringEnglish);
System.Console.Write("{0} - {1}\n", doubleGerman, doubleEnglish);


The output is: 3,1415926 - 31415926, C# does not accept the dot. This can cause a lot of confusion because nearly every programmer enters numbers with a dot and not a comma. The solution for this problem is simple:

double doubleEnglish = Convert.ToDouble(stringEnglish, CultureInfo.InvariantCulture);

This tells C# to accept the notation with the dot. If this is added to both Convert.ToDouble() above, the english string is read correctly (and the german string not).


This is the conversion from string to double. Let's face the other direction. A .ToString() method always returns the notation with the comma on my (german) computer. If I want to save data in C#, e.g. for Gnuplot, this will not work. The solution for this is as simple as the solution above:

string numberEnglish = doubleVariable.ToString(CultureInfo.InvariantCulture);

Tuesday 18 June 2013

Android - Notes App

(Deutsche Version) Many things come to my mind when I am not at home. Usually I don't have a pencil and a piece of paper with me so I wrote an App for Android. Additionally to this App, I installed Dropbox and DropSync so all my notes will be synchronized with my Dropbox folder.

Dropsync is able to sync single foldert to the Dropbox. I have a folder "toSync" on my mobile in which the notes are saved by the App and DropSync synchronizes them.

On the Computer, I can view the notes.dat file in my Dropbox folder "toSync" or edit the file. I wrote a display and edit program for Linux, maybe I will do the same for Windows. The basic principle is simple, there just has to be a window with a text field and a save button.

The app can be downloaded here. To run successfully, the folder "toSync" has to be present on the SD card and also the file "Notes.dat" has to be in this folder.

Monday 17 June 2013

C# - DirectSound

(Deutsche Version) For Panzerkampf I needed sounds. the basic sound play methon in C# is not able to play multiple sounds parallel (the current playing sound will be canceled when a new one is started). Therefor I had to install DirectSound from DirectX. For DirectX, the DirectX SDK is needed.


Previous to the installation, you should remove "Microsoft Visual C++ 2010 Redistributable", otherwise the error "S1023" occurs (here is more information about this error).

After the installation, you only need to add a reference in the C# project (Browse - Microsoft.DirectX.DirectSound, I found the file at C:\Windows\assembly\GAC\Microsoft.DirectX.DirectSound).


Additionally, App.config has to be modified a bit. At first it looked like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>


<startup> has to be modified to <startup useLegacyV2RuntimeActivationPolicy="true">, now everything looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>


The code to play sounds is the following:

Device applicationDevice = new Device();
applicationDevice.SetCooperativeLevel(this, CooperativeLevel.Priority );

soundBuffer1 = new SecondaryBuffer( "c:\afile1.wav", applicationDevice );
soundBuffer2 = new SecondaryBuffer( "c:\afile2.wav", applicationDevice );

soundBuffer1.Play( 0, BufferPlayFlags.Looping );
soundBuffer2.Play( 0, BufferPlayFlags.Looping );


Friday 14 June 2013

C# Windows Forms - Draw double buffered

(Deutsche Version) To draw everything in Panzerkampf, I used Windows Forms. A redraw event is deleting everything and then re-painting everything. This causes a very annoying flickering. To avoid this, everything is painted into an image and then the image is painted on the actual view - which will not be cleared because the image covers everything. This solves the flickering problem. Here is the code:

void drawDoubleBufBmp()
{
    Bitmap localBitmap = new Bitmap(settings.SizeX, settings.SizeY);
    using (Graphics gx = Graphics.FromImage(localBitmap))
    {
        gx.DrawDrawString("Panz.....");
    }
    lock (BmpLock)
    {
        doubleBufBmp = localBitmap;
    }
}


private Bitmap doubleBufBmp = new Bitmap(settings.SizeX, settings.SizeY);
private object BmpLock = new object();
protected override void OnPaint(PaintEventArgs e)
{
    lock (BmpLock)
    {
        g.DrawImage(doubleBufBmp, 0, 0);
    }
}

protected override void OnPaintBackground(PaintEventArgs e)
{}


I had to overwrite OnPaintBackground because this was causing the flickering. In the OnPaint function, I simply draw the complete doubleBufBmp in the Window. drawDoubleBufBmp() is called by a thread every 10 milliseconds, which then calls this.Invalidate(); which causes the OnPaint function to be called.

Monday 10 June 2013

Minecraft Server - Find out the players' positions with C#

(Deutsche Version) I am running a small (private) Minecraft server. After some time it became necessary to have a map where you can see every player.


The players' positions are saved on the server in the directory /world/players/<name>.dat and will be refreshed every 45 seconds. This is not very much but ok for a coarse map.


To read the .dat files, I use the library "LibNbt", https://github.com/aphistic/libnbt, because of the files being saved in binary format and not as plain text. After the download, simply extract everything and include the LibNbp projct into the own C# project and add a reference.

The code to read the position is the following:

DirectoryInfo d = new DirectoryInfo(@"world\players\");
var file = new NbtFile();
//A file in which the positions are saved
StreamWriter outFile = new StreamWriter("positions.dat");
string lines = "";
//run through all players
foreach (var file1 in d.GetFiles("*.dat"))
{
    //load player file
    file.LoadFile(d + file1.Name);
    NbtCompound root = file.RootTag;
    int i = 0;
    //run through all tags until the Pos tag is found
    foreach (NbtTag tag in root.Tags)
    {
        if (tag.Name.Equals("Pos"))
        {
            NbtList posList = ((NbtList)root[i]);
            //save as string
            lines += file1.Name.Substring(0,file1.Name.Length-4)

                                  + "\t"
                  + ((NbtDouble)posList[0]).Value
                                  + "\t"
                  + ((NbtDouble)posList[2]).Value
                                  + "\r\n";
        }
        i++;
    }

}
outFile.WriteLine(lines);
outFile.Close();

To show everything on a map, I used the program "AMIDST" for making a screenshot of my world (from -4096, -3072 to 4096, 3072). After that I calculate the players' positions in pixel and paint them on the map with another program which is only used for displaying.