AdSense

Posts mit dem Label Quadrocopter werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Quadrocopter werden angezeigt. Alle Posts anzeigen

Sonntag, 14. Dezember 2014

Arduino - Barometrischen Höhensensor GY-65 auslesen

(English version) Eine weit verbreitete Möglichkeit, relative Höhen zu messen ist das Benutzen eines barometrischen Höhensensors. Dieser misst einfach den Druck und aus der barometrischen Höhenformel (Wikipedia) lässt sich daraus eine Höhe bestimmen. Da der Luftdruck sehr stark vom Tag abhängt wird normalerweise an einer bekannten Höhe der Sensor kalibriert und dann die restlichen Höhen relativ zu dieser Höhe und dem dort gemessenen Druck berechnet. Das liefert Höhen mit einer Genauigkeit von bis zu 1 Meter.

Wenn man bei ebay nach GY-65 sucht, findet man den entsprechenden Sensor für ca. 5 Euro. Der Sensor hat ein normales I2C-Interface, sodass nur 2 Kabel nötig sind. Für den Arduino braucht man dann die I2Cdev Library, die gibt es hier zum runterladen. Der Quellcode an sich ist maximal simpel, zuerst wird der Sensor initialisiert, dann wird eingestellt, dass der Druck gemessen werden soll und anschließen der Druck ausgelesen und daraus die Höhe berechnet. Ein komplettes, simples Beispielprogramm sieht so aus:


#include <I2Cdev.h>
#include "BMP085.h"
#include <Wire.h>

BMP085 barometer;

double pressure;
double altitude;


void setup() {
  Wire.begin();
  
  Serial.begin(9600);
  Serial.println("starting...");
    
  //initialize the barometer
  barometer.initialize();
}

void loop()
{
  // request pressure (3x oversampling mode, high detail, 23.5ms delay).
  // Let's just wait a bit more to be sure...
  barometer.setControl(BMP085_MODE_PRESSURE_3);
  delay(30);
  // read calibrated pressure value in Pascals (Pa)
  pressure = barometer.getPressure();
  // calculate absolute altitude in meters based on known pressure
  // (may pass a second "sea level pressure" parameter here,
  // otherwise uses the standard value of 101325 Pa)
  altitude = barometer.getAltitude(pressure); 
  
  // print back the calculated altitude
  Serial.println(altitude);
  // do this every second
  delay(1000);
}

Samstag, 31. August 2013

Beschleunigungssensor MPU-6050 mit ATMega 16A auslesen

(English version) Der Beschleunigungssensor MPU-6050 ist ziemlich vielseitig, klein und billig. Er kann mit bis zu 6 V betrieben werden und liefert Beschleunigungswerte und sogar Gyroskopwerte (also Drehung in Grad pro Sekunde). So ein Sensor ist also das ideale Kernstück für einen Quadrocopter.

In diesem Post möchte ich nun auch das Auslesen mit einem ATMega zeigen, da sich der Post mit dem Raspberry PI ziemlich großer Beliebtheit erfreut (http://physudo.blogspot.de/2013/07/beschleunigungssensor-mpu-6050-mit.html). Für I2C benutze ich am ATMega diese Implementierung: http://physudo.blogspot.de/2013/07/atmega-ic-master.html.

Zuerst einmal habe ich mir zwei Funktionen gebastelt, die entweder ein Register auslesen oder in ein Register reinschreiben:

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


Als nächstes möchte ich die Beschleunigung bzw. die Werte des Gyrometers auslesen. Zu beachten ist, dass zuerst der Sleep Mode deaktiviert werden muss, das geschieht mit TWIM_WriteRegister(107, 0). Zum auslesen der Werte habe ich mir wieder 2 Funktionen gebaut:

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


Die Werte sind in Grad / Sekunde für das Gyrometer und in Einheiten von g für den Beschleunigungsmesser, mehr dazu gibt es auch in der Register Map, besonders bei der Erklärung von FS_SEL und AFS_SEL: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

Sonntag, 21. Juli 2013

Beschleunigungssensor MPU-6050 mit Raspberry PI auslesen

(English version) Der Beschleunigungssensor MPU-6050 ist ziemlich vielseitig, klein und billig. Er kann mit bis zu 6 V betrieben werden und liefert Beschleunigungswerte und sogar Gyroskopwerte (also Drehung in Grad pro Sekunde). So ein Sensor ist also das ideale Kernstück für einen Quadrocopter.

Da man mit einem Raspberry PI deutlich einfacher debuggen kann als mit Atmegas habe ich den Beschleunigungssensor zuerst mal mit dem Raspberry PI angesteuert. Das Grundprinzip ist ziemlich einfach, man muss nur einmal herausfinden wie es geht. Ich benutze am Raspberry PI die bcm2835-Library (http://www.airspayce.com/mikem/bcm2835/).

Das ganze lässt sich mit I²C auch über einen ATmega machen, dafür benutze ich diese Implementierung von I²C, dieser Post hilft da sicherlich weiter.

Um jetzt z.B. die x-Beschleunigung (Am Raspberry PI) auszumessen geht man folgendermaßen vor:

#include <bcm2835.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main (int atgc, char** argv)
{
    bcm2835_init();
    bcm2835_i2c_begin();

    char addr = 0x68;

    //I found this address somewhere in the internet...
    char buf[1];
    char regaddr[2];
    int x = 0;
    int ret;

    bcm2835_i2c_setSlaveAddress(addr);

    //disable sleep mode!!!!!

    regaddr[0] = 107;
    regaddr[1] = 0;
    //This is the basic operation to write to an register
    //regaddr[0] is the register address
    //regaddr[1] is the value
    bcm2835_i2c_write(regaddr, 2);
   
    regaddr[0] = 59;
    ret = BCM2835_I2C_REASON_ERROR_DATA;
    while(ret != BCM2835_I2C_REASON_OK)
    {
        //This is the basic operation to read an register
        //regaddr[0] is the register address
        //buf[0] is the value
        bcm2835_i2c_write(regaddr, 1);
        ret = bcm2835_i2c_read(buf, 1);
    }
    x = buf[0]<<8;

    regaddr[0] = 60;
    ret = BCM2835_I2C_REASON_ERROR_DATA;
    while(buf[0] == 99)
    {
        bcm2835_i2c_write(regaddr, 1);
        ret = bcm2835_i2c_read(buf, 1);
    }
    x += buf[0];


    //because of the sign, we have here 32-bit integers,
    //the value is 16-bit signed.

    if (x & 1<<15)
    {
        x -= 1<<16;
    }

    double x_val = x;
    x_val = x_val / 16384;

    //This is only valid if the accel-mode is +- 2g
    //The range can be controlled via the 
    //GYRO_CONFIG and ACCEL_CONFIG registers

    printf("accel: %g\n", x_val);

    bcm2835_i2c_end();
}


Dies kann jetzt natürlich noch beliebig erweitert werden, um Beschleunigungs-Werte und Gyro-Werte auszulesen. Da hiermit aber der grundlegende Zugriff auf die Register geklärt sein sollte, werde ich hier nur auf die Register Map verweisen: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

Montag, 24. Juni 2013

Quadrocopter - Erste Auftriebsmessung mit Motor und ESC

(English version) Ich habe heute einmal den Auftrieb von einem bei Ebay gekauften Motor und Propeller getestet. Es handelt sich dabei um diesen Motor (Der Preis ist vermutlich falsch, ich habe 9,75 gezahlt) mit diesem Steuergerät. Dazu habe ich noch einen 10x4,5 Propeller benutzt (welcher zwar eigentlich nicht zum Motor passt, aber ich hatte den gerade zur Hand). Das Fazit: 238 Gramm Auftrieb.

Die Spezifikationen des Motors sind: 1200 kV, 25 A maximal, 18 A kontinuierlich. Die des Steuergerätes sind: 25 A maximal, 20 A kontinuierlich. Da ich davor keinerlei Ahnung hatte, wie viel was ausmacht, habe ich nun grobe Werte die sagen, mit wie viel Auftrieb man rechnen kann.

Meine Messung sieht folgendermaßen aus: Der Motor ist auf einem Gestell aus Lego auf einer Waage befestigt. Die Geschwindigkeit wird über einen ATmega eingestellt (siehe dazu ATmega - ESC ansteuern), welcher ein Potentiometer ausliest und dementsprechend die Geschwindigkeit einstellt. Die Messanordnung sieht folgendermaßen aus:

Samstag, 25. Mai 2013

ATmega - ESC ansteuern

(English version) Ich habe heut meinen Brushless-Motor aus China bekommen, das Steuergerät (ESC) kam schon eine Woche früher an. Nun wollte ich natürlich den Motor bewegen. Ich habe vieles im Internet zum Thema "ESC, PWM" gelesen aber eine genaue Anleitung wie es wirklich funktioniert gab es nicht.

Ein ESC ist folgendermaßen aufgebaut: 3 Kabel für den Motor (welches Kabel an welches am Motor kommt ist prinzipiell egal, falls der Motor sich falschrum dreht müssen einfach 2 vertauscht werden), 2 Kabel für den Akku (+, -) und 3 Kabel für das Steuern der Motor-Geschwindigkeit per PWM.

PWM funktioniert prinzipiell so, dass der Ausgang für eine gewisse Zeit des Zyklus an ist und dann aus geht. Beim ATMega zählt ein Counter bis 255 hoch. Setzt man nun den PWM-Ausgang auf einen Wert (z.B. 150), so ist der Ausgang während dem Zählen von 1 bis 150 high und dann von 150 bis 255 low. Wie das mit dem ATMega funktioniert sieht man unten im fertigen Programm.

Die 3 ESC-Kabel sind bei mir schwarz (geht an Masse), rot (wird nicht verbunden) und weiß (hier kommt das PWM-Signal hin). Ich steuere den ESC mit einem ATMega an, der hat ja Hardware-PWM. Um den Motor benutzen zu können muss aber erstmal eine Sequenz durchgefahren werden:
1) Das "Maximale-Leistung"-PWM-Signal, bis der Motor ein paar mal piepst (bei mir ist das 250)
2) Das "Keine-Leistung"-PWM-Signal, der Motor piepst dann andere Töne (bei mir 150).
Nun kann man ein PWM-Signal (bei mir von 150 bis 250) anlegen und den Motor dementsprechend steuern.

Hier mein Code um den ESC zu kalibrieren und dann den Motor auf voller Leistung anzuschalten:

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

int main( void )
{
  DDRB=0xFF; //Alle PORTB-Anschlüsse als Ausgang festlegen
  OCR2=250; //250 von 255, also fast die ganze Zeit high
  TCCR2=0x6D; //Frequenz auf etwas mehr als 50 Hz einstellen

  _delay_ms(10000);//Warten bis der Motor piepst
              //(10 Sekunden sind schon zu viel, aber zu viel schadet ja nicht)
  OCR2 = 150;((//150 von 255, also das Minimale-Leistung-Signal für den ESC
  _delay_ms(10000);
//Warten bis der Motor fertig ist

  //Jetzt ist der ESC kalibriert und kann verwendet werden.
  //OCR2 = 150: Minimale Leistung
  //OCR2 = 250: Maximale Leistung

  OCR2 = 200;//Auf halbe Leistung schalten
  while (1)
  {}
}