My latest autopilot with new ADXRS453 gyros is ready for testing.
- 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
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.
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