AdSense

Sunday, 27 October 2013

Arduino-Code on the ATmega 1284P

(Deutsche Version) Running Arduino code on an ATmega 1284P is pretty simple. You only have to execute some small steps. At first, you have to download the following archive:
https://github.com/maniacbug/mighty-1284p/zipball/master
The content has to be extracted to C:\Program Files (x86)\Arduino\hardware\mighty-1284p (respectively the location where you installed the development environment). Afterwards, the development environment has to be restarted. Now, the 1284 can already be selected. I use the Original Mighty 1284p 16MHz. The pin mapping is different, see below (The number in the Parentheses  is relevant for the Arduino):

                      +---\/---+
           (D 0) PB0 1|        |40 PA0 (AI 0 / D24)
           (D 1) PB1 2|        |39 PA1 (AI 1 / D25)
      INT2 (D 2) PB2 3|        |38 PA2 (AI 2 / D26)
       PWM (D 3) PB3 4|        |37 PA3 (AI 3 / D27)
    PWM/SS (D 4) PB4 5|        |36 PA4 (AI 4 / D28)
      MOSI (D 5) PB5 6|        |35 PA5 (AI 5 / D29)
  PWM/MISO (D 6) PB6 7|        |34 PA6 (AI 6 / D30)
   PWM/SCK (D 7) PB7 8|        |33 PA7 (AI 7 / D31)
                 RST 9|        |32 AREF
                VCC 10|        |31 GND
                GND 11|        |30 AVCC
              XTAL2 12|        |29 PC7 (D 23)
              XTAL1 13|        |28 PC6 (D 22)
      RX0 (D 8) PD0 14|        |27 PC5 (D 21) TDI
      TX0 (D 9) PD1 15|        |26 PC4 (D 20) TDO
RX1/INT0 (D 10) PD2 16|        |25 PC3 (D 19) TMS
TX1/INT1 (D 11) PD3 17|        |24 PC2 (D 18) TCK
     PWM (D 12) PD4 18|        |23 PC1 (D 17) SDA
     PWM (D 13) PD5 19|        |22 PC0 (D 16) SCL
     PWM (D 14) PD6 20|        |21 PD7 (D 15) PWM
                      +--------+

Thursday, 24 October 2013

Control RGB LED with ATmega16A

(Deutsche Version) RGB LEDs are pretty interesting (e.g. if they are in an LED strip). Today, I want to explain how to control an RGB LED with an ATmega16A. At first a short introduction to the RGB LED: I use this LED from Tayda Electronics. This LED consists of three different LEDs which are all in the same body. Therefore, there are 3 pins for the different LEDs and a common cathode (-). If you apply a PWM signal to these 3 pins, you can control the color of the LED. I use the ATmega16A because the ATmega8 only has 2 PWM channels, this is not enough for 3 pins. This should cover the basics for an RGB LED, here is the code which runs through the whole colour space:

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

int main(void)
{
  DDRA = 0xFF;//Output
  DDRD = 0xFF;
  ICR1 = 256;
  TCCR2 = (1<<WGM20) | (1<<COM21) | (1<<CS20); // PWM, phase correct, 8 bit.
  TCCR1A = (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // PWM, phase correct, 8 bit.
  TCCR1B = (1<<CS10);// | (1<<CS10); // Prescaler 64 = Enable counter, sets the frequency
  double rCounter = 255;
  double rMax=255;
  double bCounter = 255;
  double bMax = 180;
  double gCounter = 0;
  double gMax = 70;
  int stages = 0;
  while(1)
  {
    switch (stages)
 {
   case 0:
     bCounter --;
     if (bCounter <= 0)
  {
    stages = 1;
  }
  break;
      case 1:
     gCounter ++;
     if (gCounter >= 255)
  {
    stages = 2;
  }
  break;
   case 2:
     rCounter --;
     if (rCounter <= 0)
  {
    stages = 3;
  }
  break;
   case 3:
     bCounter ++;
     if (bCounter >= 255)
  {
    stages = 4;
  }
  break;
   case 4:
     gCounter --;
     if (gCounter <= 0)
  {
    stages = 5;
  }
  break;
   case 5:
     rCounter ++;
     if (rCounter >= 255)
  {
    stages = 0;
  }
  break;
 }
 OCR1B = (int)(bCounter*bMax*bCounter/255/255);
 OCR1A = (int)(gCounter*gMax*gCounter/255/255);
 OCR2 = (int)(rCounter*rMax*rCounter/255/255);

 _delay_ms(5);
  }

}

Tuesday, 8 October 2013

C# - List all files in folder and sub folders

(Deutsche Version) Reading all files in a folder is pretty simple (see also C# Tipps and Tricks). If you want to do this recursively, the solution is also simple. The code I therefore use is the following:

var allfiles = System.IO.Directory.GetFiles(
  @"C:\YourFolder",  
  "*.*"
  System.IO.SearchOption.AllDirectories);

foreach (string file in allfiles) {}

To filter this result, you can add a .Where at the end, the following code will only list audio files:

var allfiles = System.IO.Directory.GetFiles( 
  @"C:\YourFolder"
  "*.*"
  System.IO.SearchOption.AllDirectories).Where(
    s => s.EndsWith(".mp3") || 
    s.EndsWith(".wav") || 
    s.EndsWith(".wma"));  

foreach (string file in allfiles) {}

Monday, 7 October 2013

LCD Display with Arduino / ATmega

(Deutsche Version) I bought this LCD module and this I2C controller. In this post, I will explain how to display text on the display. At first, you need the LiquidCrystal_I2C library from here. (I took the newest Version). Now you can directly start in the Arduino development enviroment. At first the includes:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

Next, you have to define several things which are (in the library) not suitable for my LCD module:

#define I2C_ADDR    0x20

#define BACKLIGHT_PIN  3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

#define  LED_OFF  1
#define  LED_ON  0

Now you have to define the display:

LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

Next, you can start in the setup()-function. At first, you have to tell the program what kind of display you have (the size, I have a 20 x 4 character display).

  lcd.begin (20,4);
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(LED_ON);

The rest is needed if you want to switch on the backlight with lcd.backlight();. Afterwards, the display is resetted:

  lcd.clear();
  delay(1000);
  lcd.home();

Now you can write things onto the display:

  lcd.print("Hello, world!");

To place the cursor at a specified position, you have to do the following:

  lcd.setCursor(5,1);

This should cover all basic functions. To delete everything, simply call lcd.clear(); .

A small hint, this problem took some time for me to solve: If you program an ATmega and then plug it into a pin board, usually nothing works, the ATmega needs a reset after it is plugged into the pin board. This could be caused by the fact that the ATmega already starts running when only some pins are connected to the pin board.

Sunday, 29 September 2013

Raspberry PI - C++ - Open socket

(Deutsche Version) Today, I want to show how to open a socket in C++. The reason for this post is: I have a Raspberry PI who does lot of things like reading temperature, controlling several things in the house. Handling the communication to the Raspberry PI via files is not a good solution, so I want to communicate directly vie network with the Raspberry PI. Therefore, the Raspberry PI has to open a network socket. I copied the code from other sources and adapted it a bit. I only need the receiving and the sending of messages. I also defined the message length to 256 bytes. The code for opening a socket is the following:

//define variables 
int sockfd, newsockfd, portno = 82; //number of port
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n; 
 
//create socket 
sockfd = socket(AF_INET, SOCK_STREAM, 0);

bzero((char *) &serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

bind(sockfd, (struct sockaddr *) &serv_addr,
        sizeof(serv_addr));
listen(sockfd,5);
clilen = sizeof(cli_addr); 
 
//accept tcp clients 
while(true)
{
  //accept client 
  newsockfd = accept(sockfd, 
            (struct sockaddr *) &cli_addr, 
            &clilen); 
  bzero(buffer,256);
  //read client message into buffer
  n = read(newsockfd,buffer,256);
  //write message to client
  n = write(newsockfd,"I got your message, this should be 256 bytes long",256);

  close(newsockfd);
}
close(sockfd);

Friday, 27 September 2013

Raspberry PI - C++ - Threads

(Deutsche Version) Implementing threads in C# is pretty simple. To use threads with C++ on a Raspberry PI, you have to do some small things which are not necessary in C#. You have to place #include <thread> on the top. Then you can create a thread like this:

std::thread networkThread (networkCommunication);
networkThread.detach();


To compile this program, you have to add two things to the compile command in the terminal:

-std=c++0x
-pthread


The whole program is compiled like this:

g++ ./myProgram.c++ -o outputName -std=c++0x -pthread

Now you should be able to create threads on your Raspberry PI.

Tuesday, 24 September 2013

The influence of the Coriolis force on a sniper bullet

(Deutsche Version) Some time ago, I watched the film Shooter (Wikipedia). In the early stages, a shot over a distance of 1,5 km is mentioned. It is also mentioned that for such a shot, even the Coriolis force has an effect. Today, I want to calculate this.

At first a short introduction about the topic Coriolis force. The Coriolis force is one of the pseudo forces which occurs in rotating frames. The force can be derived simply by transforming the equation of motion of a free particle into a rotating frame (for more information, see e.g. H.-R. Trebin, Theoretische Physik 1, Mechanik). For my calculation, this is not necessary. Basically, the Coriolis force occurs because the earth turns away under the projectile.

Let's face the calculation. To get a maximum influence of the Coriolis force, I assume that the shot is parallel to a line of longitude. Assuming a degree of latitude of 45°, the target is about 1 km farther from the rotation axis of the earth, so the target moves quicklier perpendicular to the trajectory than the projectile. Now I want to calculate these velocities. The diameter of the earth is about 12730 km. In the 45. degree of latitude, this equals a radius of about 4500 km, leading to a perimeter of 28274 km. With a time of circulation of 86400 seconds, this leads to a velocity of 327.245 m/s. If the radius is increased about 1 km, the new perimeter is 28281 km and the new velocity 327.326 m/s. This causes a difference of 0.081 m/s.

In the film, a time of flight of 6 to 10 seconds is mentioned, this would cause a deviation of 0.5 to 0.8 meters. I personally think that the time of flight is much shorter, a projectile with 1000 m/s only needs 1.5 seconds for this distance, so the deviation is about 12 cm (which still could decide wheter it is a hit or not).

Real Time Clock DS1307

(Deutsche Version) Sometimes you need the date or time for your Arduino projects, for example for data logging. In this case, a so called real time clock module like "Tiny RTC" comes in very handy. It is based on a DS1307 and has a backup battery. It keeps on counting the time, even if your Arduino is not longer connected to a power supply.

The DS1307 is connected via I2C. You just have to connect the power supply and SDA and SCL with the according pins on your Arduino. It is important to use pins on the right side of the module (the side with 7 pins). With the pins on the other side you can connect the EEPROM-IC which is also soldered to the board.

You can read date and time (year, month, day, weekday, hour, minute, second) from your RTC module. These values are stored in a SRAM register and can be interfaced via I2C. 
Register 0: bits 0 to 6 store the seconds - bit 7 indicates if the clock is running or not. When the bit is set to 1 - the clock will stop. 
Register 1: bits 0 to 6 store the minutes.
Register 2: if bit 6 is set, the hours are stored in 12h-format. Bit 5 indicates wheter it's AM or PM. The hours are stored in bit 0 to 4. If bit 6 is cleared, the hours are stored in 24h-format in bits 0 to 5.
Register 3: weekdays can be read from bits 0 to 3. If the register is set to 1, it's Sunday, 2 means Monday and so on.
Register 4 to 6: date, month and year
Register 7: some configuration-stuff we won't need.
The following register can be used as battery-powered RAM and can be read and written as desired.

All numbers are stored in BCD-format (Binary Coded Decimal). For example, the number 18 would be 0001'1000, 34 would be 0011'0100 and so on.

The address of the DS1307 in I2C-bus is 0x68.

Before first use, you have to set the correct time:

#include "Wire.h"

#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
    
  Serial.begin(9600);
  
  byte second =      0; //0-59
  byte minute =      44; //0-59
  byte hour =        22; //0-23
  byte weekDay =     1; //1-7
  byte monthDay =    22; //1-31
  byte month =       9; //1-12
  byte year  =       13; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
    
  Wire.write(0x00); //set pointer to register 0
  
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.endTransmission();
  
}

void loop(){
}

byte decToBcd(byte val){
//convert decimal to BCD
  return ( (val/10*16) + (val%10) );
}

In the variables you have to set the correct date and time. With beginTransmission() you start communicating with the module. After setting the pointer to register 0 (where the seconds are stored), you can transmit date and time: the values stored in the variables are converted to BCD and then written to the register. After each write()-command, the Arduino automatically jumps to the next register.


Once the DS1307 is set correct, it keeps on counting the time until the end of time (or its battery). Date and time can be accessed with the following code:


#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  
  //set pointer to register 0
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(0x00);
  Wire.endTransmission();

  //get time
  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read());
  int weekDay = bcdToDec(Wire.read());
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print date and time in format dd.mm.yy - hh:mm:ss
  Serial.print(monthDay);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".");
  Serial.print(year);
  Serial.print(" - ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
  delay(1000);
}

byte bcdToDec(byte val)  {
//convert BCD to de cimal
  return ( (val/16*10) + (val%16) );
}

At first the pointer is set so register 0 (since we want to start reading the seconds). After that, 7 bytes of data are requested with requestFrom(). The data is read(), converted to decimal and stored in variables. At the end, date and time are printed via serial.

Wednesday, 18 September 2013

ATMega - Everything slowed down about the factor of 8?

(Deutsche Version) This problem occured recently: I have an ATmega 1284-P which has a 16 MHz quarz. Sadly, everything was slower as expected, with a factor of 8. The fuses (I use AVR Studio 4, there you don't see every fuse) were ok. After some time on Google, I found out what the problem was: The fuse-bit CKDIV8 is 0, this means that the clock is divided by 8. Sadly, this fuse bit cannot be set with the AVR Studio 4, but there is a simple solution to disable the clock divider:

#include <avr/power.h> 

And then directly at the beginning of the program:

clock_prescale_set(clock_div_1);


This solved the problem for me.

Tuesday, 17 September 2013

Music player - Remote for android mobile phones

(Deutsche Version) As described in this post, I created an own music player in C# and WPF. It can occur that you don't like the current playing song, so there are hotkeys for the computer. But what is, when you are lying on the bed and don't want to get up to switch to the next song? Therefore, I created an App, which can execute the basic commands (play/pause, next song, previous song). The app can be downloaded hier.

The app can be started an then you can click on the buttons, but there is also a widget which does not require the click to open the app. The app contains more functions, you can even look for a song.

In the app, you have to enter IP, Port (the player opens a socket on port 7200) and password (which you can define in the player with F2). The IP can be local (e.g. when the mobile phone is in the same network as the computer) or an internet IP. Therefore, you have to setup the appropriate port forwarding at your router. The mobile phone can now control the player independant of whether it is in the wireless network or in the mobile network.

Monday, 16 September 2013

Android - Write application data

(Deutsche Version) Lots of Android apps use a several (small) amount of memory for "data". These datas are e.g. for saving passwords or similar things. I want to explain how to access these datas. At first the reading:

SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
String defaultStringValue = "";
String stringValue = sharedPref.getString("nameOfString", defaultStringValue);


This is analogue to a C# Dictionary with a string as key and (here) a string as value. The value can also be an integer, the syntax is the same. If the key does not exist, defaultStringValue is returned.

Now to the writing of application data:

SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
String stringValue = "asdf";
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("
nameOfString", stringValue);
editor.commit();


Here you can also use int instead of string. Additionally, you can have multiple editor.put... commands directly in a row and only at the end there has to be the editor.commit();. This should cover the basic access on application data. If you want to acces on application data via a widget, you have to use SharedPreferences. The only thing that changes in the code is:

SharedPreferences sharedPref = this.getSharedPreferences("nameOfPreferences", 0);

Wednesday, 11 September 2013

Pin Change Interrupt with the ATmega or Arduino

(Deutsche Version) Lots of microcontrollers (e.g. an ATmega168) do not only have external interrupts but also so called Pin Change Interrupts. These interrupts work on all channels. The basic idea is: When something changes at a channel, an interrupt function is called. These interrupts are not as comfortable as the "normal" external interrupts, you only get the information "something changed on some channel" and not which channel or if this channel is now high or low.


I will explain now with the ATmega168 how this works. I use the channels PB0, PD5..7 as interrupt channels. To activate the interrupts, I have to do the following:

PCICR |= (1 << PCIE0)|(1 << PCIE2);

This activates the interrupts for PCINT0 and PCINT2, this means PORTB and PORTD. Now I have to define the channels which shall cause these interrupts:

PCMSK0 |= (1 << PCINT0);
PCMSK2 |= (1 << PCINT23)|(1 << PCINT22)|(1 << PCINT21);


Now you only have to activate the interrupts (sei();). If you use the Arduino development environment, everything until now happens in the setup function. Now you have to define three functions which are called when an interrupt is triggered. They have to have the following names:

ISR(PCINT2_vect)
{
}


and

ISR(PCINT0_vect)
{
}


To find out which channel had an interrupt, you can read the channels and check if something changed. Or if you just have 4 switches, you can easily check which switch is pressed:

int Button0 = digitalRead(8); 
int Button1 = digitalRead(7); 
int Button2 = digitalRead(6);  
int Button3 = digitalRead(5);

Monday, 9 September 2013

Comparison of different lamps

(Deutsche Version) Today I want to compare three lamps which could be suitable as room light. The candidates are:
a) An "old" halogen bulb
b) A helical energy-effective lamp (Link)
c) A COB-LED (Link)

At first the specifications:
a) Power: 40 W
luminous flux: 390 Lum
life time: 2 000 h
price: 2 €

b) Power: 23 W
luminous flux: 1 550 Lum
life time: 10 000 h
price: 8 €

c) Power: 7 W
luminous flux: 560 Lum
life time: >10 000 h (no value on Pollin.de, approximately 25 000 h)
price: 6 € (with heat sink, the LED only costs 3 €)

The first point of comparison is: How much light comes out of how much power? I show the values in Lum/W:
a) 10
b) 67
c) 80
The LED and the energy-effective lamp are clearly winning at this point.

The next point: how much light comes out of how much money? Here are the values in Lum/€:
a) 195
b) 194
c) 95
The LED looses this competition because LEDs are more expensive.

As the most important point of comparison I want to light a room for 5 years. I assume 5000 Lum and 6 hours of light per day, this are about 2000 hours. How many lamps would I need to reach the 5000 Lum?
a) 13
b) 3
c) 9
If you consider the life time, all halogen bulbs have to be switched every year, whilst the energy-effective lamp and the LED survive the whole 5 Jears. This increases the costs for the halogen bulbs by a factor of 5. The prices for the lamps are:
a) 128
b) 26
c) 53
consider: The costs for the LED are 50% for the heat sink. Now i want to examine the power consumption:
a) 1026 kWh
b) 148 kWh
c) 125 kWh
If I assume 20 ct / kWh, the costs for 5 jears are:
a) 205
b) 30
c) 25

The cheapest one is the energy-effective lamp. For the LED: Please note that the costs are basically only 50% because of the heat sinks. Additionally, an LED lasts much longer than an energy-efficient lamp, in the long term, the LED wins this competition because it also has a slightly smaller power consumption.

LED room light - selfmade

(Deutsche Version) At Pollin, there are COB-LEDs for sale (Pollin). The great thing about them is that they don't need any resistor or anything else, you just have to apply the suitable voltage and a heat sink.
560 lm is quite a lot, I will compare different light sources in a different post. The great advantage of LEDs is that they are effective and have a very high life time so maybe the future belongs to LEDs. The only problem with this LED is that the light comes out of a very small area and the LED is very bright and is eventually dangerous for the eye. Therefore, I had to build a lamp shade. I used greaseproof paper. The instructions are very simple, you only should ensure that b > a/2, otherwise there will be a hole in the middle.
Cut along the red edges. Afterwards fold the vertical dottet lines about 90° so the paper makes a closed cylinder. Afterwards, the flaps have to be folded over and the whole thing is some kind of bucket which can be put over the lamp. The final result is the following:

Sunday, 8 September 2013

Read and write SD cards with Arduino

If you want to use your Arduino as a datalogger, you might face the problem where to store the logged data. The best way to deal with it is storing it on a SD card. The data is safe even if the Arduino is powered off, you can connect the card directly to your computer and read the data for example with Matlab oder Excel.

Hardware

On Ebay you can find very cheap SD card modules for Arduino. I bought the module by LC Technology:
Pin mapping is clearly visible. There are pin for voltage supply (+5V, +3.3V and GND) and for SPI-bus which is used to read and write the SD card. The pins in the upper row are connected to the pins in the lower row. SD cards work with a voltage level of 3.3V. The module can be supplied with either 3.3V or 5V (a voltage regulator is included). There is NO level converter for the SPI pins so you MUST NOT connect these pins directly to your Arduino. You would destroy your card.



The module is supplied with 5V by the Arduino. The SPI pins are connected using a level converter:
MOSI to Pin 11
MISO to Pin 12
SCK to Pin 13
CS to Pin 4

I used a bi-directional level converter and converted all of the pins. Both things are technically not necessary. You could use a converter that only converts for 5V to 3.3V (e.g. 74HC4050) and you only have to convert MOSI, SCK and CS. MISO can be connected directly to the Arduino.

When everything is wired correctly, you can put a SD card into the module. The card has to be formated as FAT16 or FAT32. According to the Arduino reference FAT16 is preferred. 

Software

The SD-library for Arduino brings several examples to test your hardware. I chose the example "datalogger" which writes the values of three analog inputs to a txt-file on the SD card.

#include <SD.h>

const int chipSelect = 4;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ","; 
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
}

In setup()-function a serial connection is established, the command SD.begin(chipSelect) initializes the SD card. The parameter is the pin CS is connected to. If initialization was succesfull we continuer to loop(). Here the values of the analog inputs are read and saved to a string variable. With the command SD.open() the file "datalog.txt" is opened in write mode. If the file was opened succesfull, the value of the string variable is wirtten to the file and the file is closed.

Reading files on the card is pretty easy, too:

  dataFile = SD.open("test.txt");
  if (dataFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (dataFile.available()) {
     Serial.write(dataFile.read());
    }
    // close the file:
    data.close();
  } else {
   // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

At first the file is opened with the open()-command. Then it can be read line by line with read() until the end of the file is reached (this is checked with the available()-command). In the end, the file is closed with close().

Friday, 6 September 2013

C# - Global hotkeys which are really global

(Deutsche Version) My music player uses hotkeys. Basically, the work fine. When playing several computer games (e.g. Leauge of Legends), the hotkeys do not work anymore. To solve this problem, I used an implementation from my friend from http://csharp-tricks-en.blogspot.de/ and adapted this implementation a bit. My hotkeys are now in a separate class which is used this way:

KeyHook MyHook = new KeyHook(this, KeyboardHookProcedure);
MyHook.Hook(KeyHook.KeyboardHookProc);

KeyHook.KeyPressed += KeyHook_KeyPressed;
KeyHook.KeyReleased += KeyHook_KeyReleased;


Die KeyHook_KeyPressed und KeyHook_KeyReleased Funktionen sehen folgendermaßen aus:

void KeyHook_KeyPressed(int keyCode, List<int> pressedKeys)
{}


keyCode is simply an integer, which value represents which key is listed here. I added the events KeyPressed and KeyReleased to have a clean solution. Now the code of the class KeyHook:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace anyNamespace
{
    public class KeyHook
    {
        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        //Declare hook handle as int.
        static int hHook = 0;

        //Declare keyboard hook constant.
        //For other hook types, you can obtain these values from Winuser.h in Microsoft SDK.
        const int WH_KEYBOARD_LL = 13;

        public delegate void KeyPressedEventHandler(int keyCode, List<int> pressedKeys);
        public static event KeyPressedEventHandler KeyPressed;

        public delegate void KeyReleasedEventHandler(int keyCode, List<int> pressedKeys);
        public static event KeyReleasedEventHandler KeyReleased;

        [StructLayout(LayoutKind.Sequential)]
        private class keyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //Import for SetWindowsHookEx function.
        //Use this function to install thread-specific hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
        IntPtr hInstance, int threadId);

        //Import for UnhookWindowsHookEx.
        //Call this function to uninstall the hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //Import for CallNextHookEx.
        //Use this function to pass the hook information to next hook procedure in chain.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode,
        IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        //static Form1 View;
        static MainWindow mainWindow;

        const int MOD_SHIFT = 0x0004;

        IntPtr LL = (IntPtr)LoadLibrary("User32");

        public KeyHook(MainWindow _mainWindow, HookProc proc)
        {
            mainWindow = _mainWindow;
            Hook(proc);

        }

        ~KeyHook()
        {
            UnHook();
        }

        HookProc _proc;
        public int Hook(HookProc proc)
        {
            _proc = proc;
            hHook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, LL, 0);
            return hHook;
        }

        public bool UnHook()
        {
            bool ret = UnhookWindowsHookEx(hHook);
            if (ret)
                hHook = 0;
            return ret;
        }

        public static List<int> pressedKeys = new List<int>();

        public static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                return CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {
                keyboardHookStruct MyKeyboardHookStruct = (keyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(keyboardHookStruct));
                if ((MyKeyboardHookStruct.flags & 128) == 128)
                {
                    if (pressedKeys.Contains(MyKeyboardHookStruct.vkCode))
                    {
                        pressedKeys.Remove(MyKeyboardHookStruct.vkCode);
                        if (KeyReleased != null)
                        {
                            KeyReleased(MyKeyboardHookStruct.vkCode, pressedKeys);
                        }
                    }
                }
                if ((MyKeyboardHookStruct.flags & 128) == 0)
                {
                    if (!pressedKeys.Contains(MyKeyboardHookStruct.vkCode))
                    {
                        pressedKeys.Add(MyKeyboardHookStruct.vkCode);
                        if (KeyPressed != null)
                        {
                            KeyPressed(MyKeyboardHookStruct.vkCode, pressedKeys);
                        }
                    }
                }
                return CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }
    }
}

Monday, 2 September 2013

C# WPF - Invoke

(Deutsche Version) In the previous post there was this problem: I am only allowed to access graphics from the main thread. Unfortunately it can occur that you want to edit something from another thread. The solution for this problem is: invoke. At first a small example which does not work:

void threadActivity()
{
    Thread.Sleep(5000);
    TaskbarItemInfo.ProgressValue = 0.2;
}


After 5 seconds, there will be an error: InvalidOperationException has not been handled. The calling thread cannot acces this object, because the object belongs to another thread. As announced, the solution is called invoke. The new code looks like this:

void threadActivity()
{
    Thread.Sleep(5000);
    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
    {
        TaskbarItemInfo.ProgressValue = 0.2;
    }));
}


After 5 seconds, the progress bar in the task bar will be set to the value 0.2. About the syntax: Everything inside the curly braces is executed in the main thread. Inside the curly braces you can access variables which are also accessible from outside the curly braces. You can also have lots of code in here, but I would recommend to only invoke small code blocks.

C# WPF - Show progress in task bar

(Deutsche Version) Downloading something with firefox will show the progress in the task bar. Realising this is pretty simple. In the window you want to have this, you have to add

<Window.TaskbarItemInfo>
    <TaskbarItemInfo/>
</Window.TaskbarItemInfo>


just in front of the <Grid>. Now you can access TaskbarItemInfo. This could be done like this:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();


        TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal;
 
        Loaded += MainWindow_Loaded;
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        TaskbarItemInfo.ProgressValue = 0.5;

    }
}


You can use different ProgressStates so the progress bar changes its color. You can also define a symbol for the task bar.

If you want to do all these things from another thread, this will not work. Why is explained in this post. I will only show the solution. Instead of

TaskbarItemInfo.ProgressValue = 0.2

you have to use

Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
    TaskbarItemInfo.ProgressValue = 0.2;
}));

Android - Widget "crashes" when the screen is being rotated

(Deutsche Version) The detailled error is: I have got an widget, when I click on it, I want it to open the corresponding app. This usually works. Sometimes, nothing happens when I click on it, mostly after turning the screen. The reason is: Several things (e.g. rotating the screen) do not call the onUpdate function but only the onReceive function. Because of having the following lines in the onUpdate


Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

remoteViews.setOnClickPendingIntent(R.id.button, pendingIntent);


the MainActivity was started. This did not happen when onReceive was called. Therefore, I had to add these lines to the onReceive function (I had to rename intent in localIntent because onReceive has a parameter Intent intent). Afterwards, everything worked fine.

Saturday, 31 August 2013

Read acceleration sensor MPU-6050 with ATMega 16A

(Deutsche Version) In this post, I will show how to read the values of an MPU-6050 with an ATMega 16A. For the usage of I2C on the ATMega, I use this implementation.

If you want to use a Raspberry PI instead of an ATMega, see this post.

At first, I wrote two functions which can read from a register respectively write to a register:

void TWIM_WriteRegister(char reg, char value)
{
    TWIM_Start(addr, TWIM_WRITE); // set device address and write mode
    TWIM_Write(reg);
    TWIM_Write(value);
    TWIM_Stop();
}

char TWIM_ReadRegister(char reg)
{
    TWIM_Start(addr, TWIM_WRITE);
    TWIM_Write(reg);
    TWIM_Stop();

    TWIM_Start(addr, TWIM_READ); // set device address and read mode
    char ret = TWIM_ReadNack();
    TWIM_Stop();
    return ret;
}


As a second step, I wrote two functions which read the acceleration and gyro data from the Sensor. Please note that you have to disable the sleep mode, this can be done by using TWIM_WriteRegister(107, 0).

double MPU6050_ReadAccel(int axis)//x = 0; y = 1; z = 2
{
  char reg = axis * 2 + 59;
  char AFS_SEL = TWIM_ReadRegister(28);
  double factor = 1<<AFS_SEL;
  factor = 16384/factor;
  int val = 0;
  double double_val = 0;
  char ret = 0;

  ret = TWIM_ReadRegister(reg);
  val = ret << 8;

  ret = TWIM_ReadRegister(reg+1);  
  val += ret;

  if (val & 1<<15)
  val -= 1<<16;

  
  double_val = val;

  double_val = double_val / factor;

  return double_val;
}

double MPU6050_ReadGyro(int axis)//x = 0; y = 1; z = 2
{
  char reg = axis * 2 + 67;
  char FS_SEL = TWIM_ReadRegister(27);
  double factor = 1<<FS_SEL;
  factor = 131/factor;
  int val = 0;
  double double_val = 0;
  char ret = 0;

  ret = TWIM_ReadRegister(reg);
  val = ret << 8;

  ret = TWIM_ReadRegister(reg+1);  
  val += ret;

  if (val & 1<<15)
  val -= 1<<16;



  double_val = val;
 
  double_val = double_val / factor;

  return double_val;
}


The values for the gyrometer are in degrees per second and in units of g for the accelerometer, further information is provided in the Register Map, especially at the explaination of FS_SEL and AFS_SEL: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

Thursday, 29 August 2013

Header image depending on the time of day

I created a homepage where I wanted to change the header image depending on the time of day. In the daytime I wanted an image of a building by day, in the nighttime an image of the same building by night.

This can be done pretty easy with PHP.

At first the current time hast to be  stored in variable:

$time = date("G", time())

time() function returns the UNIX timestamp of the server. The UNIX timestamp is the number of seconds since 01.01.1979 at 1 AM. To get the timestamp to a "readable" format we use the date() function. The format is chose with the first paramter. "G" delivers the the hours without leading zero. A lot of other formats are possible, you can find them on this website.

The current hour is saved in the variable called $time. It is important to know that time is stored in UTC (coordinated universal time). I needed MEZ (or MESZ) so I had to add one (two) hours.

Now the header image can be chosen according to the current time:

if ($time > 7 && $time < 21 ) {
   $path = "http://yourserversdomain.de/images/header_day.jpg";
 }

else {
    $path = "http://yourserversdomain.de/images/header_night.jpg";
}

If the number of hours is greater than 7 and less than 21 (it is between 8:00 and 20:59) the path of the "day image" is stored to the variable $path - else the path of the "night image".


Then the image is embedded using HTML:

<img src="<?php echo $path; ?>" width="123" height="456" alt="" />


Of course you could also use this method for creating images depending on the weekday or the season.

Wednesday, 28 August 2013

Arduino code on ATtiny

As you can read in my last posts I am working at a remite control at the moment. For this purpose the "normal" ATmega8 isn't the best choice (too big, too expensive, 5V supply voltage). So the project is based on an ATtiny, but I still want to use the features and the libraries of the Arduino IDE. How you can use the IDE to programm an ATmega8 can be read in my first post on this blog. It was pretty easy because Arduino supports the ATmega8 out of the box.
For the ATtiny, a few more steps have to be taken. With the following instructions you can add the ATtiny45, ATtiny85, ATtiny24, ATtiny44 and ATtiny84 to the Arduino IDE.

First of all you have to download this file. The containing folder "attiny" must be copied to the folder "hardware" in your Arduino installation. It should look like this: "C:\Programs\Arduino\hardware\attiny".


The folder contains the file "boards.txt". It contains the information to the used "boards" (fuse settings, clock frequency,...) - in our case it's only the ATiny. Only the "boards" listed in this file will appear in the IDE. The file only includes the settings for the use of the internal clock source. For an external clock source, you have to adapt the settings. In this case it's important so set the correct fuses, otherwise you will have timing problems.

Now you have to tell the IDE the pin settings of your ATTiny. The folder "variants" in the archive you just downloaded  contains the subfolders "tiny8" and "tiny14". In these folders you can find a file named "pins_arduino.h" which specifies the pin mapping of the Tiny. In the file you can also see which pin of the ATtiny has which "Arduino function". For ATTiny24/44/84 this would be for example



                                          +-\/-+
                                VCC  1|    |14  GND
                      (D 10)  PB0  2|    |13  AREF (D  0)
                       (D  9)  PB1  3|    |12  PA1  (D  1)
                                 PB3  4|    |11  PA2  (D  2)
    PWM  INT0  (D  8)  PB2  5|    |10  PA3  (D  3)
       PWM        (D  7)  PA7  6|    |9   PA4  (D  4)
       PWM        (D  6)  PA6  7|    |8   PA5  (D  5)        PWM
                                          +----+

When you start the Arduino IDE, you should see the ATtiny under "Tools-Board":

From now on, it's business as usual. Depending on the used ATiny, there might be some restrictions, e.g. with interrupts. Furthermore your have to use a programmer like the USBasp to programm the Tiny.

These instructions are also valid for every other ATtiny (and ATmega) - you just have to find the right "pins_arduino.h" or create it for yourself.

C# WPF - DataBinding

(Deutsche Version) DataBindings in WPF are very powerful and useful. Today, I will explain the basics. The basic idea is: I have a display element and a variable (technically: field). When I change my variable, I want the display element to change and vice versa, so the variable will change if the display element changes (e.g. a text is entered into a TextBox). At first the XAML part of the code:

<TextBox Name="InputText" Grid.Row="0" Text="{Binding BindingText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
<TextBlock Name="OutputText" Grid.Row="1" Text="{Binding BindingText, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"></TextBlock>


As a next step, I need an object to which I am doing the DataBinding. In my case, this is the class "AnyClass" which containt the field "BindingText". I could also simply use MainWindow.xaml.cs. To define the object to which the bining should be, you have to do the following:

AnyClass anyClass = new AnyClass();
InputText.DataContext = anyClass;
OutputText.DataContext = anyClass;


I could also do this.DataContext = anyClass;, this would have the same effect but I want to show different possibilities how to do DataBinding. I also could also create the field "BindingText" in MainWindow.xaml.cs and then do this.DataContext = this;.

Now I want to face the class AnyClass. At first a short introduction to fields. A field can be used just like a variable but it cannot hold values directly. The minimum field would be this:

public string BindingText
{
    get { return _BindingText; }
    set { _BindingText = value; }
}
private string _BindingText = "";


This is a field. The get and set parts can do lots of funny things like checking the input, throw events, and everything else.

Now I will show the class AnyClass which is the last missing part for the DataBinding:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataBindingExample
{
    public class AnyClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string BindingText
        {
            get { return _BindingText; }
            set
            {
                _BindingText = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("BindingText"));
                }
            }
        }
        private string _BindingText = "<empty>";
    }
}


By calling PropertyChanged, the display element gets the information that there is a new variable value and refreshes the displayed value. This should cover the basics for DataBinding. If there are further questions, I will answer them in the comments.

 A post about this topic who also covers converters can be found on C# Tips and Tricks.

Friday, 23 August 2013

A music player with C#

(Deutsche Version) There are a lot of music players on this world. Every player has its advantages and disadvantages. Until now, I was not able to find the "perfect" music player. Therefore I wrote my own music player which can be downloaded here. A bit about the handling: At first, a folder has to be specified as music library. Then, by clicking on "Refresh Library", all music files in this directory are laoded. Hotkeys were very important for me, so I implemented them (see below). I will present two important parts of the music player: Playing music with WPF and using Hotkeys. By the way, you can find a basic introduction to WPF here: C# Tips and Tricks.

Playing music

Hence I use WPF, playing music is very simple: In my xaml file, I have a MediaElement:

<MediaElement Height="10" Width ="10"  LoadedBehavior="Manual" Name="mediaElement1" VerticalAlignment="Top" />

The MediaElement is invisible. To play music, you have to execute the following code:

mediaElement1.Source = new Uri(pathToMediaFile);
mediaElement1.Play();


This is the whole magic for playing music. You can now do several things like registering to events so you know when the actual song has finished playing (to start the next song).

Hotkeys

Note: By now I use a "better" implementation of the hotkeys which you can find here.

Using hotkeys is pretty simple. At first, you have to add several lines into the program:

[DllImport("User32.dll")]
private static extern bool RegisterHotKey(
    [In] IntPtr hWnd,
    [In] int id,
    [In] uint fsModifiers,
    [In] uint vk);

[DllImport("User32.dll")]
private static extern bool UnregisterHotKey(
    [In] IntPtr hWnd,
    [In] int id);

private HwndSource _source;
private const int HOTKEY_ID = 9000;

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    var helper = new WindowInteropHelper(this);
    _source = HwndSource.FromHwnd(helper.Handle);
    _source.AddHook(HwndHook);
    RegisterHotKey();
}

protected override void OnClosed(EventArgs e)
{
    _source.RemoveHook(HwndHook);
    _source = null;
    UnregisterHotKey();
    base.OnClosed(e);
}

private void UnregisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    UnregisterHotKey(helper.Handle, HOTKEY_ID);
}

private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_HOTKEY = 0x0312;
    switch (msg)
    {
        case WM_HOTKEY:
            OnHotKeyPressed(wParam.ToInt32());
            break;
    }
    return IntPtr.Zero;
}


As a next step, I defined the three hotkeys I need:

private void RegisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    const uint VK_RIGHT = 0x27;
    const uint VK_LEFT = 0x25;
    const uint VK_SPACE = 0x20;
    const uint MOD_ALT = 0x0001;
    const uint MOD_CTRL = 0x0002;

    if (!RegisterHotKey(helper.Handle, HOTKEY_ID+2, MOD_CTRL + MOD_ALT, VK_RIGHT))
    {
        // handle error
    }
    if (!RegisterHotKey(helper.Handle, HOTKEY_ID+1, MOD_CTRL + MOD_ALT, VK_LEFT))
    {
        // handle error
    }
    if (!RegisterHotKey(helper.Handle, HOTKEY_ID, MOD_CTRL + MOD_ALT, VK_SPACE))
    {
        // handle error
    }
}


Finally, I need a function which executes the desired actions when a hotkey is pressed:

private void OnHotKeyPressed(int key)//9000 = space, 9001 = left, 9002 = right
{
    //System.Console.Write("KeyPressed! {0}\n", key);
    switch (key)
    {
        case 9000: if (playing) { pause(); } else { play(); }
            break;
        case 9001: back();
            break;
        case 9002: next();
            break;
        default:
            break;
    }
    // do stuff
}


Please note: If you have a hotkey registered, e.g. "AltGr" + "0", this key combination is only available for my program. So in this example, I could not write } anymore (I have a german keyboard layout) as long as my program is opened.