AdSense

Sonntag, 27. Oktober 2013

Arduino-Code auf dem ATmega 1284P

(English version) Um Arduino-Code auf dem ATmega 1284P auszuführen muss man lediglich ein paar kleine Schritte durchführen. Zuerst muss das folgende Archiv heruntergeladen werden:
https://github.com/maniacbug/mighty-1284p/zipball/master
Der Inhalt wird dann nach C:\Program Files (x86)\Arduino\hardware\mighty-1284p entpackt (bzw. in den entsprechenden Ordner, je nachdem wohin die Entwicklungsumgebung installiert wurde). Anschließend startet man die Entwicklungsumgebung neu und kann unter Board auch schon den 1284 auswählen. Ich benutze Original Mighty 1284p 16MHz. Die Pin-Belegung ist nun natürlich auch anders und zwar wie folgt (Die Zahl in Klammern ist für den Arduino relevant):

                      +---\/---+
           (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
                      +--------+

Donnerstag, 24. Oktober 2013

RGB-LED mit ATmega16A ansteuern

(English version) RGB-LEDs sind ziemlich interessant (z.B. in LED-Streifen oder ähnlichem). Daher möchte ich heute erklären, wie man mit einem ATmega16A eine RGB-LED ansteuert. Zuerst einmal zur RGB-LED. Ich benutze diese LED von Tayda Electronics. Diese LED besteht praktisch aus drei verschiedenen LEDs welche alle in einem Gehäuse sind. Daher gibt es 3 Pins für die verschiedenen LEDs und eine gemeinsame Kathode (-). Legt man nun PWM-Signale an diese 3 Pins, so kann man die Farbe der LED einstellen. Den ATmega16A benutze ich, da der ATmega8 nur 2 PWM-Kanäle hat, das reicht leider nicht für 3 Pins. Damit ist eigentlich auch alles geklärt, hier mal der Code von mir, welcher durch den kompletten Farbkreis läuft:

#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);
  }

}

Dienstag, 8. Oktober 2013

C# - Alle Dateien in Ordner und Unterordnern anzeigen

(English version) Alle Dateien in einem Ordner auszulesen ist recht simpel (siehe dazu auch C# Tipps und Tricks). Will man das rekursiv machen ist das auch nicht weiter schwer. Der Code, welchen ich dafür benutze ist der folgende:

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

foreach (string file in allfiles) {}

Um dieses Ergebnis nun weiter zu filtern kann man ein .Where hinten anhängen, im folgenden Code werden also nur Audio-Dateien zurückgegeben:

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) {}

Montag, 7. Oktober 2013

LCD Display mit Arduino / ATmega

(English version) Ich habe mir dieses LCD-Modul gekauft und diesen I2C-Controller dafür. In diesem Post werde ich erklären, wie man nun Text auf das Display schreiben kann. Zuerst benötigt man die LiquidCrystal_I2C Library von hier. (Ich habe einfach die neueste Version genommen). Nun kann man auch schon direkt in der Arduino-Entwicklungsumgebung anfangen. Zuerst die Includes:

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

Als nächstes müssen einige Sachen definiert werden, die in der Library nicht ganz für das LCD-Modul passen:

#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

Nun muss das Display definiert werden:

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

Als nächstes fängt man in der setup()-Funktion an. Zuerst sagt man dem Programm um was für ein Display es sich handelt (also die Größe, ich benutze ein 20 x 4 Zeichen Display).

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

Den Rest benötigt man, damit man mit lcd.backlight(); die Beleuchtung anschalten kann. Danach wird das LCD-Display resettet:

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

Nun kann man Sachen auf das Display schreiben. Das geht so:

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

Um den Cursor an eine Stelle zu setzen macht man folgendes:

  lcd.setCursor(5,1);

Damit sollten die grundsätzlichen Funktionen geklärt sein. Um alles zu löschen ruft man einfach lcd.clear(); auf.

Noch ein kleiner Hinweis, dieses Problem bereitete mir am Anfang viel Kopfzerbrechen: Programmiert man einen ATmega und steckt ihn dann direkt in ein Steckbrett, so funktioniert meistens gar nichts, der ATmega braucht einen Reset, nachdem er im Steckbrett steckt. Das liegt vermutlich daran, dass der ATmega schon losläuft auch wenn nur ein paar Pins mit dem Steckbrett verbunden sind.

Sonntag, 29. September 2013

Raspberry PI - C++ - Socket öffnen

(English version) Heute will ich einen kleinen Post zum Thema Socket öffnen in C++ schreiben. Der Grund dafür ist, dass mein Raspberry PI vieles ansteuert, ausliest, etc. Das dann alles über Dateien zu regeln ist keine so schöne Lösung, daher will ich direkt über das Netzwerk mit dem Raspberry PI reden können. Dafür muss am Raspberry PI ein Netzwerk-Socket aufgemacht werden. Vieles von dem Code habe ich einfach aus anderen Quellen übernommen, da ich ja nur das Empfangen und Senden der Nachricht benötige. Außerdem habe ich die Nachrichtenlänge auf 256 Bytes festgesetzt. Das Ganze geht folgendermaßen:

//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);

Freitag, 27. September 2013

Raspberry PI - C++ - Threads

(English version) Threads in C# zu implementieren ist total einfach. Will man jedoch auf dem Raspberry PI soetwas mit C++ haben, so muss man ein paar Kleinigkeiten beachten. Ein Thread wird folgendermaßen erzeugt und gestartet, #include <thread> muss ganz oben stehen.

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


Zum Compilieren müssen jetzt aber noch zwei Optionen angegeben werden, sonst funktioniert das nicht:

-std=c++0x
-pthread


Das ganze Programm wird dann wie folgt compiliert:

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

Damit kann mann dann auch am Raspberry PI Threads erzeugen und lustige Sachen damit machen.

Dienstag, 24. September 2013

Einfluss der Corioliskraft auf ein Scharfschützen-Projektil

(English version) Vor einiger Zeit sah ich den Film Shooter (Wikipedia). Recht am Anfang wird über einen Schuss aus 1,5 km Entfernung gesprochen. Dabei wird auch erwähnt, dass bei diesem Schuss sogar die Corioliskraft eine Rolle spielt. Das will ich heute hier durchrechnen.

Zuerst eine kurze Einführung zum Thema Corioliskraft. Die Corioliskraft zählt zu den sogenannten Scheinkräften, welche in rotierenden Bezugssystemen auftritt. Die Kraft lässt sich recht einfach herleiten, indem man die Bewegungsgleichungen eines freien Teilchens in ein rotierendes Koordinatensystem transformiert (siehe dazu auch z.B. H.-R. Trebin, Theoretische Physik 1, Mechanik). Für meine Rechnung ist dies jedoch nicht vonnöten. Anschaulich erklärt tritt die Kraft auf, weil sich die Erde unter dem Geschoss weiterdreht.

Kommen wir zur Rechnung. Um eine maximale Wirkung der Corioliskraft zu haben gehe ich davon aus, dass der Schuss entlang eines Längengrades ausgeführt wird. Geht man von einem Breitengrad von etwa 45° aus, so ist das Ziel etwa 1 km weiter von der Rotationsachse der Erde entfernt, daher bewegt sich das Ziel senkrecht zur Flugbahn etwas schneller als das Projektil. Nun will ich diese beiden Geschwindigkeiten berechnen. Der Erd-Durchmesser ist etwa 12 730 km. Im 45. Breitengrad entspricht das einem Radius von ziemlich genau 4500 km, also einem Umfang von 28274 km. Das führt bei einer Umlaufzeit von 86400 Sekunden zu einer Geschwindigkeit von 327,245 m/s. Vergrößert sich der Radius nun um 1 km, so ist der neue Umfang 28281 km und die neue Geschwindigkeit 327,326 m/s. Das macht eine Differenz von 0,081 m/s.

Im Film wird von etwa 6-10 Sekunden Flugzeit gesprochen, das würde 0,5 bis 0,8 Metern Abweichung vom Ziel entsprechen. Ich persönlich schätze die Flugzeit jedoch etwas anders, ein Geschoss mit 1000 m/s braucht für die Strecke nur 1,5 Sekunden, das macht dann immerhin 12 cm aus (was bereits über Treffer oder nicht Treffer entscheiden kann).