Autopilot with XMEGA128A1 and ADXRS453 gyros

My latest autopilot with new ADXRS453 gyros is ready for testing.

3689447102?profile=original

3689447063?profile=original

3689447080?profile=original

- Two switching power supplies (Traco Power) at 6.5V and 5V for low power dissipation

-  Separated reference voltage with RLC filter for sensors

-  Separated reference voltage with RLC filter for ATXMEGA's ADC reference input

-  Separated power supply with RLC filter for MCU's digital side

- Two MCU's  ATXMEGA128A1 @ 40Mhz (40+40 MIPS), one for AHRS and one for navigation

- ADXRS453 ultra high vibration rejection gyros, digital output (SPI)

- LIS344ALH Accelerometer

- HMC5883L  3D Compass

- MPL3115A2    I2C Precision Altimeter - internal ready calculated altitude !! - saving MCU time for other tasks

- 6 R/C inputs

- 8 PWM outputs (460Hz)

- 2 PWM outputs for servo camera stabilization

- 8 digital outputs (500mA/each) for buzzer, external LED's,payload trigger,etc

- 2 spare analogical inputs @ 12bit

- 4 general purpose I/O's (I2C, UART, PWM)

- battery voltage monitoring

- Serial COM. for GPS

- Serial COM. for XBEE

- Serial COM. @ analogical input for ultrasonic Sonar

- Four LED's for GPS,XBEE,etc.

I will start doing testings with the AP in high vibration environment - by using unbalanced propellers + motors and see how well gyros will perform. In following days, MPL3115A2 will be also delivered. Just waiting to see the altitude precision of  this new IC.

Will keep you posted about testing results.

Cheers,

Sergiu

E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • Did you try the highest oversampling setting for MPL3115? With the oversampling set at 128 I obtained a rate of ~3Hz of altitude measurements which were rather stable from sample to sample  (a few centimeters). However the problem I encounter with this sensor is that it requires about 2-3 minutes of running at full speed before it actually settles on stable measurement - for the first 2-3 minutes the measurements slowly "float" up or down until they settle. 

    Attached is the chart from a test flight - MPL3115A2 was "warmed up" for 2 minutes before the flight. For this flight the sensor is configured for oversampling of 32 measurements for the effective rate of about 10 Hz (light blue line) which then smothed by the IIR filter with alpha=1/32. My data logger takes measurements every 10 msec while sensor data changes about every 100 msec, so on the chart you may see "flat" lines between the moments I obtain the new measurements. Dark blue line represent the "smoothed" sensor data.3692889722?profile=original

  • Hi

    This is the code I used a while ago:

    Rem Absolute pressure sensor
    Dim Twi_start As Byte
    Dim Alt_static As Single , Alt_temp As Single , Tmp_frac As Byte
    Dim Mpl_dev_id As Byte , Mpl_status As Byte , Mpl_int As Integer
    Dim Mpl_alt_msb As Byte , Mpl_alt_csb As Byte , Mpl_alt_lsb As Byte
    Dim Mpl_temp_msb As Byte , Mpl_temp_lsb As Byte
    Dim Byte1 As Byte At Alt_static Overlay , Byte2 As Byte At Alt_static + 1 Overlay
    Dim Byte3 As Byte At Alt_static + 2 Overlay , Byte4 As Byte At Alt_static + 3 Overlay
    Dim Timer_static As Single , Dt_static As Single
    '***************************
    Open "twic" For Binary As #3
    Config Twi = 400000
    I2cinit #3
    '***************************
    Rem Read  MPL3115A2 dev Id which should be &C4
    I2cstart #3
        I2cwbyte &HC0 , #3                                      'write addr.
        I2cwbyte &H0C , #3
    I2crepstart #3
        I2cwbyte &HC1 , #3
        I2crbyte Mpl_dev_id , Nack , #3
    I2cstop #3
    Print #2 , Hex(mpl_dev_id)
    Rem Set to Altimeter with OSR=128
    I2cstart #3
        I2cwbyte &HC0 , #3
        I2cwbyte &H26 , #3
        I2cwbyte &HB8 , #3
    I2cstop #3
    Rem Enable Data Flags in PT_DATA_CFG
    I2cstart #3
        I2cwbyte &HC0 , #3
        I2cwbyte &H13 , #3
        I2cwbyte &H07 , #3
    I2cstop #3
    Rem Set Poling active and start device
    I2cstart #3
        I2cwbyte &HC0 , #3
        I2cwbyte &H26 , #3
        I2cwbyte &HB9 , #3
    I2cstop #3
    '********************
    Declare Sub Altitude_static()

    ......................................................................

    Sub Altitude_static()
       Timer_static = Timer_static + Dt_static      ' I read sensor at every 1.3 seconds
    If Timer_static >= 1.3 Then
          Timer_static = 0

           I2cstart #3
              I2cwbyte &HC0 , #3                                'write addr.
              I2cwbyte &H01 , #3
       I2crepstart #3
        I2cwbyte &HC1 , #3
        I2crbyte Mpl_alt_msb , Ack , #3
        I2crbyte Mpl_alt_csb , Ack , #3
        I2crbyte Mpl_alt_lsb , Ack , #3
        I2crbyte Mpl_temp_msb , Ack , #3
        I2crbyte Mpl_temp_lsb , Nack , #3
       I2cstop #3
         Tmp_frac = Mpl_alt_lsb
         Shift Tmp_frac , Right , 4                             'use bit7-4
         Mpl_int = Makeint(mpl_alt_csb , Mpl_alt_msb)
         Alt_static = Tmp_frac / 10
         Alt_static = Alt_static + Mpl_int
         Tmp_frac = Mpl_temp_lsb
         Shift Tmp_frac , Right , 4                             'use bit7-4
         Alt_temp = Tmp_frac / 10
         Alt_temp = Alt_temp + Mpl_temp_msb
         'Print #2 , Alt_static ; "  " ; Alt_temp
    End If
      Reset Watchdog
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    However i came to the conclusion that no accuracy can be obtained from this digital absolute sensors. The result is jumping +/- tens of centimeters.

    The only reliable way to use in multicopters is using of something like MP3h6115A and some Sallen Key op-amp filter.

    Regards,

    Sergiu

  • I managed to interface the MPL3115A2 from Bascom.

    I had a lot of problems understanding the registry-data from the PDF but finally got hold of an excelsheet with calculations from freescale. and was much more helpful than the 13 pages PDF they have on their website.

    Here's my code regarding the sensor if anyone needs it (I only messure pressure in pascal but by changing the &H26 , &B00111011 to &H26 , &B10111011 you will get pressure data in meters but it needs a whole new calculation-method and i don't need it so i haven't made it)

    Sub Mpl3115a2(byval Sensornr As Byte)
       Print "Sensor:" ; Sensornr ; " MPL3115A2: " ;
    '   I2c_regwrite &HC0 , &H26 , &B01000000
       I2c_regwrite &HC0 , &H26 , &B00111011
       I2c_regwrite &HC0 , &H13 , &H07
    '   I2c_regread &HC0 , &H26 , Regreturn
       For Temp = 0 To 50
          Waitms 10
          I2c_regread &HC0 , &H00 , Regreturn
          If Regreturn.1 = 1 And Regreturn.2 = 1 Then           ' Check Pdata and Tdata flag
             'Calculate Pressure pascal ------------------
             I2c_regread &HC0 , &H01 , Highbyte_pressure
             I2c_regread &HC0 , &H02 , Centerbyte_pressure
             I2c_regread &HC0 , &H03 , Lowbyte_pressure
             Raw_pressure = Makeint(centerbyte_pressure , Highbyte_pressure)
             Pressure_pascal.1 = Lowbyte_pressure.7
             Pressure_pascal = Raw_pressure * 4
             If Lowbyte_pressure.4 = 1 And Highbyte_pressure < &H80 Then Pressure_pascal = Pressure_pascal + 0.25
             If Lowbyte_pressure.5 = 1 And Highbyte_pressure < &H80 Then Pressure_pascal = Pressure_pascal + 0.5
             If Lowbyte_pressure.4 = 1 And Highbyte_pressure >= &H80 Then Pressure_pascal = Pressure_pascal - 0.25
             If Lowbyte_pressure.5 = 1 And Highbyte_pressure >= &H80 Then Pressure_pascal = Pressure_pascal - 0.5
             If Lowbyte_pressure.6 = 1 Then Pressure_pascal = Pressure_pascal + 1
             If Lowbyte_pressure.7 = 1 Then Pressure_pascal = Pressure_pascal + 2
             Print " Pressure = " ; Fusing(pressure_pascal , ".##") ; " Pascal ";

             'Calculate temperature ----------------------
             I2c_regread &HC0 , &H04 , Highbyte_temperature
             I2c_regread &HC0 , &H05 , Lowbyte_temperature
             If Highbyte_temperature > &H7F Then                ' Is the temperature minus degree?
                For Temp = 0 To 7
                   Toggle Highbyte_temperature.temp
                Next
                Temperature = Highbyte_temperature
                Temperature = Temperature * -1
                Temperature = Temperature - 1
                If Lowbyte_temperature.4 = 1 Then Temperature = Temperature - 0.0625
                If Lowbyte_temperature.5 = 1 Then Temperature = Temperature - 0.125
                If Lowbyte_temperature.6 = 1 Then Temperature = Temperature - 0.25
                If Lowbyte_temperature.7 = 1 Then Temperature = Temperature - 0.5
             Else
                Temperature = Highbyte_temperature
                If Lowbyte_temperature.4 = 1 Then Temperature = Temperature + 0.0625
                If Lowbyte_temperature.5 = 1 Then Temperature = Temperature + 0.125
                If Lowbyte_temperature.6 = 1 Then Temperature = Temperature + 0.25
                If Lowbyte_temperature.7 = 1 Then Temperature = Temperature + 0.5
             End If

             Print Fusing(temperature , "##.####") ; " C ";

             Print : Exit Sub
          End If
       Next
       Print " : " ; Bin(regreturn) ; "  !!!  Error Reading Mpl3115a2, flag 00 not set , not ready timeout!!! ";
       Err = 1
       If Err = 1 Then Gosub Remove_sensor
       I2c_regwrite &HC0 , &H26 , &B01000100
       Waitms 50
       I2c_regwrite &HC0 , &H26 , &B01000000
       Print
    End Sub

    Sub I2c_regwrite(byval Chipadress As Byte , Byval Regaddr As Byte , Byval Value As Byte)
          I2cstart                                              ' Start i2c comm
          I2cwbyte Chipadress                                   ' Send adresse
          I2cwbyte Regaddr                                      ' Send adresse
          I2cwbyte Value                                        ' Send adresse
    '      I2crbyte Value , Ack                                  ' Dummy read
          I2cstop                                               ' Stop i2c comm
    End Sub

    Sub I2c_regread(byval Chipadress As Byte , Byval Regaddr As Byte , I2c_regreturn As Byte)
          I2cstart                                              ' Start i2c comm
          I2cwbyte Chipadress                                   ' Send adresse
          I2cwbyte Regaddr                                      ' Send adresse
          I2cstart
          Chipadress = Chipadress + 1
          I2cwbyte Chipadress                                   ' Send adresse
          I2crbyte I2c_regreturn , Nack                         ' read adresse
          I2cstop                                               ' Stop i2c comm
    End Sub

    Sub I2c_bus_reset
       Disable Interrupts
       Config Portc.4 = Output
       Config Portc.5 = Output
       Sda Alias Portc.4
       Scl Alias Portc.5
       Delay
       ' Create START condition (SDA goes low while SCL is high)
       Reset Sda
       Delay
       Set Scl
       Delay
       Set Sda
       Config Portc.4 = Input
       Delay
       ' Clock SCL for at least 9 clocks until SDA goes high */
       ' This loop is significantly greater than 9 clocks to */
       ' make sure that this condition is met. */
       For Temp = 0 To 100
          Set Scl
          Delay
          Reset Scl
          Delay
          If Sda = 1 And Temp > 9 Then Exit For
          If Temp = 100 Then Print "I2C Reset Fail!!!";
       Next
       Config Portc.4 = Output
       Delay
       ' Create STOP condition (SDA goes high while SCL is high)
       Reset Sda
       Delay
       Set Scl
       Delay
       Set Sda
       Delay
       Enable Interrupts
    End Sub

  • I managed to interface the MPL3115A2 from Bascom.

    I had a lot of problems understanding the registry-data from the PDF but finally got hold of an excelsheet with calculations from freescale. and was much more helpful than the 13 pages PDF they have on their website.

    Here's my code regarding the sensor if anyone needs it (I only messure pressure in pascal but by changing the &H26 , &B00111011 to &H26 , &B10111011 you will get pressure data in meters but it needs a whole new calculation-method and i don't need it so i haven't made it) Sub Mpl3115a2(byval Sensornr As Byte)
       Print "Sensor:" ; Sensornr ; " MPL3115A2: " ;
    '   I2c_regwrite &HC0 , &H26 , &B01000000
       I2c_regwrite &HC0 , &H26 , &B00111011
       I2c_regwrite &HC0 , &H13 , &H07
    '   I2c_regread &HC0 , &H26 , Regreturn
       For Temp = 0 To 50
          Waitms 10
          I2c_regread &HC0 , &H00 , Regreturn
          If Regreturn.1 = 1 And Regreturn.2 = 1 Then           ' Check Pdata and Tdata flag
             'Calculate Pressure pascal ------------------
             I2c_regread &HC0 , &H01 , Highbyte_pressure
             I2c_regread &HC0 , &H02 , Centerbyte_pressure
             I2c_regread &HC0 , &H03 , Lowbyte_pressure
             Raw_pressure = Makeint(centerbyte_pressure , Highbyte_pressure)
             Pressure_pascal.1 = Lowbyte_pressure.7
             Pressure_pascal = Raw_pressure * 4
             If Lowbyte_pressure.4 = 1 And Highbyte_pressure < &H80 Then Pressure_pascal = Pressure_pascal + 0.25
             If Lowbyte_pressure.5 = 1 And Highbyte_pressure < &H80 Then Pressure_pascal = Pressure_pascal + 0.5
             If Lowbyte_pressure.4 = 1 And Highbyte_pressure >= &H80 Then Pressure_pascal = Pressure_pascal - 0.25
             If Lowbyte_pressure.5 = 1 And Highbyte_pressure >= &H80 Then Pressure_pascal = Pressure_pascal - 0.5
             If Lowbyte_pressure.6 = 1 Then Pressure_pascal = Pressure_pascal + 1
             If Lowbyte_pressure.7 = 1 Then Pressure_pascal = Pressure_pascal + 2
             Print " Pressure = " ; Fusing(pressure_pascal , ".##") ; " Pascal ";

             'Calculate temperature ----------------------
             I2c_regread &HC0 , &H04 , Highbyte_temperature
             I2c_regread &HC0 , &H05 , Lowbyte_temperature
             If Highbyte_temperature > &H7F Then                ' Is the temperature minus degree?
                For Temp = 0 To 7
                   Toggle Highbyte_temperature.temp
                Next
                Temperature = Highbyte_temperature
                Temperature = Temperature * -1
                Temperature = Temperature - 1
                If Lowbyte_temperature.4 = 1 Then Temperature = Temperature - 0.0625
                If Lowbyte_temperature.5 = 1 Then Temperature = Temperature - 0.125
                If Lowbyte_temperature.6 = 1 Then Temperature = Temperature - 0.25
                If Lowbyte_temperature.7 = 1 Then Temperature = Temperature - 0.5
             Else
                Temperature = Highbyte_temperature
                If Lowbyte_temperature.4 = 1 Then Temperature = Temperature + 0.0625
                If Lowbyte_temperature.5 = 1 Then Temperature = Temperature + 0.125
                If Lowbyte_temperature.6 = 1 Then Temperature = Temperature + 0.25
                If Lowbyte_temperature.7 = 1 Then Temperature = Temperature + 0.5
             End If

             Print Fusing(temperature , "##.####") ; " C ";

             Print : Exit Sub
          End If
       Next
       Print " : " ; Bin(regreturn) ; "  !!!  Error Reading Mpl3115a2, flag 00 not set , not ready timeout!!! ";
       Err = 1
       If Err = 1 Then Gosub Remove_sensor
       I2c_regwrite &HC0 , &H26 , &B01000100
       Waitms 50
       I2c_regwrite &HC0 , &H26 , &B01000000
       Print
    End Sub

    Sub I2c_regwrite(byval Chipadress As Byte , Byval Regaddr As Byte , Byval Value As Byte)
          I2cstart                                              ' Start i2c comm
          I2cwbyte Chipadress                                   ' Send adresse
          I2cwbyte Regaddr                                      ' Send adresse
          I2cwbyte Value                                        ' Send adresse
    '      I2crbyte Value , Ack                                  ' Dummy read
          I2cstop                                               ' Stop i2c comm
    End Sub

    Sub I2c_regread(byval Chipadress As Byte , Byval Regaddr As Byte , I2c_regreturn As Byte)
          I2cstart                                              ' Start i2c comm
          I2cwbyte Chipadress                                   ' Send adresse
          I2cwbyte Regaddr                                      ' Send adresse
          I2cstart
          Chipadress = Chipadress + 1
          I2cwbyte Chipadress                                   ' Send adresse
          I2crbyte I2c_regreturn , Nack                         ' read adresse
          I2cstop                                               ' Stop i2c comm
    End Sub

    Sub I2c_bus_reset
       Disable Interrupts
       Config Portc.4 = Output
       Config Portc.5 = Output
       Sda Alias Portc.4
       Scl Alias Portc.5
       Delay
       ' Create START condition (SDA goes low while SCL is high)
       Reset Sda
       Delay
       Set Scl
       Delay
       Set Sda
       Config Portc.4 = Input
       Delay
       ' Clock SCL for at least 9 clocks until SDA goes high */
       ' This loop is significantly greater than 9 clocks to */
       ' make sure that this condition is met. */
       For Temp = 0 To 100
          Set Scl
          Delay
          Reset Scl
          Delay
          If Sda = 1 And Temp > 9 Then Exit For
          If Temp = 100 Then Print "I2C Reset Fail!!!";
       Next
       Config Portc.4 = Output
       Delay
       ' Create STOP condition (SDA goes high while SCL is high)
       Reset Sda
       Delay
       Set Scl
       Delay
       Set Sda
       Delay
       Enable Interrupts
    End Sub

  • Did you get the MPL3115A2 to work?

    I have always used SPI parts and have never written an I2C communication before.

    If you want to share your code it would be great!

    I also use Bascom for programming. everyone around me asks why i don't code in C but as long as i can use Basic i will continue to use it. it's like mother-language to me, and brings me way back to zx Spectrum and commodore times :-)

  • Thank you again.
    Good luck!

    (Am going to read the link provided).

  • Eugenijus

    So far I am one man show. So it takes longer time to finish one project than team working. On the other hand it have only my mistakes...For more info on two MCU's AP see my other post :

    http://diydrones.com/profiles/blogs/xmega-ap-and-esc

    Regards,

    Sergiu

  • Thank you. Sounds good.
    Have you a team for programming all stuff, or you it by yourself only? It is not as simple question as it look at a fist glance - it is the we will observe it flying. Have you a some deadline?

    Yours,
    Eugenijus

  • Euginijus,

    At the beginning I made Ap's with even 4 MCU's. All of them ATmega. One was doing R/C reading, another GPS and compass,etc. I did a big step forward when XMEGA came out. With it, I made my first AP with one MCU only. It was possible not because of higher MIPS but because of DMA. Later, keeping navigation (R/C input, PWM output, GPS, Sonar) in one MCU and AHRS ( gyro,accelerometer,compass) in another MCU, given me more processing power and more MCU peripherals. However is nothing about " do not keep all eggs in same basket " because any of the MCU will fail, the copter will crush.  Having only one MCU with enough MIPS and DMA (like STM32) it is also OK. You don't need to bother anymore about MCU's data exchange.

    Regards,

    Sergiu

  • Sergiu,

    Can you explain for us your choice with 2 CPU?
    We have a hot discussion about it on microcopetr.ru (in Russian).

    I suppose you do it because of simplifying IN and OUT processes (RC+sensors and Output to motors and other stuff). My opponent ask me "why not one, more sophisticated multikernel CPU?".
    Because of reliability and simplicity?

    Yours,
    Eugenijus

This reply was deleted.