AdSense

Showing posts with label Quadrocopter. Show all posts
Showing posts with label Quadrocopter. Show all posts

Sunday, 14 December 2014

Arduino - Read out height sensor GY-65

(Deutsche Version) A common way to measure relative heights is the usage of a barometric height sensor. Such a sensor measures the pressure and by using the barometric formula (Wikipedia), one can calculate the height. The ambient pressure varies during the days therefore the sensor is calibrated at a well-known height and the other heights are calculated by using this reference pressure and height. The measured heights have a precision of up to 1 meter.

If  you look for the GY-65 at ebay, you can find the sensor for about 5 euro. The sensor has a usual I2C interface so only two wires are needed. Additionally, the I2Cdev library is needed which can be downloaded here. The source code is as simple as possible, at first the sensor is initialised, then measuring the pressure is set and afterwards the pressure is read out and calculated into the height. A basic program looks like this:


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

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

Sunday, 21 July 2013

Read acceleration sensor MPU-6050 with Raspberry PI

(Deutsche Version) To read the MPU-6050 via a Raspberry PI, a I²C library is needed. I used the bcm2835 library (http://www.airspayce.com/mikem/bcm2835/). To read the acceleration, i used the following C code. It is very important to disable the sleep mode (set register 107 to 0), otherwise the sensor will not work properly.

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

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


All other applications should be simple with this code, the Register Map will provide further information: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

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:

Saturday, 25 May 2013

ATMega - Control an ESC

(Deutsche Version) I recently bought an brushless motor and an electronic speed controller. In this post, I want to explain what kind of signal has to be applied to the ESC to move the motor.

An ESC is constructed like this: 3 cables for the motor, 2 cables the battery and 3 cables for the PWM signal. The motor cables can be connected to any motor cable, if the motor spins into the wrong direction, simply switch two cables.

PWM is the shortcut for pulse width modulation. This means, for a several amount of time, there is a high signal and then a low signal. This is often used to set the brightness of LEDs. At an ATMega, a counter counts to 255. If i set my PWM channel to some value, e.g. 150, the output will be high from 1 to 150 and then low until 255.

The three cables of the esc are black (connected to ground), red (not connected) and white (connected to the PWM output). To calibrate the motor, a sequence has to be executed:
a) Maximum power signal (PWM channel set to  250)
b) Minimum power signal (PWM channel set to 150)
Now the motor speed will be linear dependant on the length of the PWM, 150 equals no power and 250 equals maximum power. Here is the code for an ATMega8:


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

int main( void )
{
  DDRB=0xFF; //Define all PORTB-channels as output
  OCR2=250; //250 of 255, nearly all time high
  TCCR2=0x6D; //Frequency set to a bit more than 50 Hz

  _delay_ms(10000);//Wait until the motor starts beeping
  OCR2 = 150;((//150 of 255, this is the no-power signal
  _delay_ms(10000);
//wait until the motor is calibrated

  //Now the ESC is calibrated and can be used:
  //OCR2 = 150: Minimum power
  //OCR2 = 250: Maximum power

  OCR2 = 200;//Set to 50% power
  while (1)
  {}
}