SlideShare a Scribd company logo
1 of 8
Download to read offline
QUADCOPTER FLIGHT CONTROLLER BASED ON KALMAN FILTERS – ITSP PROJECT DOCUMENTATION
I am using Arduino Due in my project. I recently bought it from Amazon.
First I decided to start learning arduino due using Arduino IDE. Just for testing, I uploaded an arduino
code to extract data out of MPU 6050 using i2c bus and display it through Serial display. On the very
first run everything works fine. But when I removed the programming cable and reattached it to the
PC and opened the serial monitor, I didn’t get any data. I rechecked everything and still got the same
problem. So, I started debugging the code to find if the program is going into infinite loop or something
else is wrong.
What I found was the code was going into infinite loop in the following line of code
Wire.requestFrom(0x68 , 14);
while (Wire.available() < 14) Serial.println('.'); //Debug
On searching online, I found that many people have been complaining about problems regarding the
i2c communication in arduino due. I found many arduino forums discussing the same. I tried to search
how to fix the problem but I couldn’t get any proper solution. I found some chunks of code which
manipulated register settings which I didn’t understand.
Rather than looking up at the internal header files of Arduino, that may be causing the problem, I
decided to switch to Atmel studio so that I can understand the register settings and port manipulation
better. Also the header files of Arduino IDE contain many lines of codes that are irrelevant for the user
and can sometimes cause head-scratching problems like the one above.
Arduino Due runs on atsam3x8e or simply sam3x8e, an ARM microprocessor. Unlike AVR processors
such as atmega328p (on Adruino Uno), ARM Processors run at 3.3V logic level, are faster and more
complex. I downloaded the sam3x8e datasheet from here and an unofficial Arduino Due pin out
diagram from here. The official Arduino Due schematic is available here. For my project, the functions
I needed to use on due was to:
• Find a way to UPLOAD programs from Atmel studio to sam3x8e without using any
external programmer
• Make sam3x8e run at FULL CLOCK SPEED i.e. 84MHz
• Declare Pins as INPUT / OUTPUT and drive the required logic level
• Create TIMER functions similar to micros() or delay() (as in Arduino IDE) to create
delays of specific time interval
• Activate TWI Interface to communicate with I2C sensors
• Activate UART Function to communicate with the PC (Serial Monitor of Arduino IDE)
• Activate and enable INTERRUPT service to generate interrupt whenever state of pins
toggle
• Activate ANALOG Pins and use them as INPUT
And the following points are why I need them in my project. Some of them are obvious, so I marked
them obvious.
• UPLOAD: Obvious.
• FULL CLOCK SPEED: The faster, the better off course.
• INPUT / OUTPUT: Obvious.
• TIMER: Obvious.
• TWI: Most of the sensors in my project use I2C Interface.
• UART: To print data in the Serial Monitor and to talk with the GPS.
• INTERRUPT: To read receiver signals while flying.
• ANALOG: To determine battery voltage while flying.
FIND A WAY TO UPLOAD PROGAMS FROM ATMEL STUDIO WITHOUT EXTERNAL PROGRAMMER
Arduino Due has two ports: The Programming Port (ATMEGA16U2) and the Native USB Port (SAM3X).
At first, I tried to copy the way Arduino IDE uploads the program to atsam3xe via Programming Port
(Atmega16U2). I checked the “Show Verbose Output during Upload” of the Arduino IDE and copied
the “Commands and Arguments” to create a new external tool in the Atmel Studio. Although it worked
for Arduino Uno and Leonardo (AVR Processor based boards), it didn’t work for Arduino Due. I am not
mentioning the exact way I did it, as it didn’t work anyway. What I learnt was: just like ‘avrdude.exe’
is required to program AVR Processors, ‘bossac.exe’ is required to program ARM Processors.
As I couldn’t figure out how to upload code via Programming Port, I switched to Native USB Port. I
found this website which neatly describes how to upload via Native USB Port. I followed the steps and
it worked just fine.
MAKE SAM3X8E RUN AT 84MHz
On creating a new project on Atmel Studio and selecting device as sam3x8e, in the main program, a
function called SystemInit() was called by default. On searching what it does, I found that it
configures the system to run at 84MHz. The code in the declaration of SystemInit() is well
commented and can be easily understood by referring the datasheet.
DECLARE PINS AS OUTPUT AND RUN REQUIRED LOGIC LEVEL
Going through the datasheet, under section 31. Parallel Input/Output Controller, I found all the
register settings needed to declare a pin as output. To declare pin 13(which is connected to on-board
LED) of Arduino Due which is pin B27 of sam3x8e (see the pin out), the code is:
PIOB->PIO_PER |= PIO_PER_P27; //PIO Enable Register (not required though)
PIOB->PIO_OER |= PIO_OER_P27 ; //Output Enable Register
The first line is not required as PIO Controller is enabled by default after reset. But if the pin is
configured to work as a peripheral (specially assigned functions), the PIO Controller needs to be
enabled first.
To drive it high:
PIOB->PIO_SODR |= PIO_SODR_P27; //Set Output Data Register
To drive it low:
PIOB->PIO_CODR |= PIO_CODR_P27; //Clear Output Data Register
DECLARE PINS AS INPUT AND READ THEIR LOGIC LEVEL
Going further in the same section as above, I found the register settings for declaring pins as input. To
declare pin 12 of Arduino Due which is pin D8 of sam3x8e (see the pin out), the code is:
PIOD->PIO_PER |= PIO_PER_P8; //PIO Enable Register (not required though)
PIOD->PIO_ODR |= PIO_ODR_P8; //Output Disable Register
The status of the pin (HIGH or LOW) can be read from the PDSR (Pin Data Status Register). In the
following code, the value of state is 1 when pin 12 is HIGH, and 0 when pin 12 is LOW.
uint16_t state = (PIOD->PIO_PDSR & PIO_PDSR_P8)>>8; //Read the PIO_PDSR register
But the code didn’t work at all. I rechecked the datasheet and found that unlike just declaring pins as
input/output, there was an additional instruction that said:
“Reading the I/O line levels requires the clock of the PIO controller to be enabled, otherwise PIO_PDSR
reads the levels present on the I/O line at the time the clock was disabled”.
I searched the datasheet, but didn’t find a clue how to enable the clock. So I advanced further, and
while writing the code for UART initialization, I stumbled upon this forum, where someone mentioned
about enabling the peripheral clock for UART. So I referred to the Peripheral Identifier section of the
datasheet and found a list of PIDs (Peripheral Identifiers) and their corresponding peripheral. I found
the peripheral PIOD with PID 14. Then I included the line of code (mentioned below) in my ‘declaring
pins as input ‘ program, and pin 12 is successfully declared as input and everything works fine. PCER0
stands for Peripheral Clock Enable Register 0.
PMC->PMC_PCER0 |= PMC_PCER0_PID14; //Enable PIOD Clock
Afterwards, I found another way to enable Peripheral Clock.
PMC->PMC_PCER0 |= (1u<<ID_PIOD); //Enable PIOD Clock
I also found that the PCER0 register is actually write protected. Zero needs to be written in the WPEN
bit (Write Protect Enable) to disable the Write Protect Mode.
But my code still runs without any problem. Maybe the Write Protect Mode was already undone by
SystemInit().As my code was working anyway, I didn’t bother to check up. And following is the code
to disable the Write Protect Mode.
PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN); //Disable the Write Protect Mode
CREATE TIMER FUNCTIONS TO CREATE DELAYS OF SPECIFIC INTERVALS
In my project, I need a precision of at most 1 us. So I need a clock frequency of at least 1 MHz. There
are two sections in the datasheet through which we can create such timers. One is Section 13 RTT
(Real Time Timer) and the other is Section 36 TC (Timer Counter).
The RTT runs through the SWCLK (SLOW CLOCK) that has a clock frequency of 32.768 kHz, thus, is
not suitable for this project.
The TC can be made to run from 5 internal clock sources, that are MCK/2, MCK/8, MCK/32, MCK/128
and SWCLK (MCK refers to MAIN CLOCK). As sam3x8e is running at 84 MHz (MCK), the usable
frequencies are MCK/2, MCK/8 and MCK/32. I chose to use MCK/8 or 10.5 MHz for my clock frequency.
I found this blog which may be useful. The following is the code used for setting up the timer.
//Configure PMC
//Disable the Write Protect Mode
PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN);
//Enable TC0 Peripheral Clock
PMC->PMC_PCER0 |= PMC_PCER0_PID27;
//Disable the Write Protect Mode
TC0->TC_WPMR &= ~(TC_WPMR_WPEN);
//Set Clock Source to MCK/8
TC0->TC_CHANNEL[0].TC_CMR |= TC_CMR_TCCLKS_TIMER_CLOCK2;
//Set Wave select to updown
TC0->TC_CHANNEL[0].TC_CMR |= TC_CMR_WAVE | TC_CMR_WAVSEL_UPDOWN;
//Enable Clock and trigger to start counter
TC0->TC_CHANNEL[0].TC_CCR |= TC_CCR_CLKEN | TC_CCR_SWTRG;
The following line of code is used to load the real time counter value onto a variable.
//Read current value from Counter Value Register
uint32_t counter = TC0->TC_CHANNEL[0].TC_CV;
ACTIVATE TWI INTERFACE TO COMMUNICATE WITH I2C SENSORS
This part is described in the datasheet under Section 33 Two-Wire Interface (TWI).There are two TWI
channels. I’m using the second channel (TWI1) which are pins SDA and SCL of Arduino Due and pins
B12 and B13 of sam3x8e (see the pin out).
First of all, I programmed the PIO controller to dedicate TWD and TWCK as peripheral lines. Then,
enabled the peripheral clock. And set the mode of operation to Master Mode. The steps of using TWI
in different modes are neatly displayed in a flowchart at the end of the TWI section.
The line of code to set up the speed to 400 kHz actually overwrites the line of code above it which sets
the speed to 100 kHz. To run at 100 kHz, just uncomment the line corresponding to 400 kHz.
The following is the code to set up the I2C interface at 400 kHz. Note that the prefix “0x” is to represent
the number as hexadecimal.
https://forum.arduino.cc/index.php?topic=373307.0
https://forum.arduino.cc/index.php?topic=146802.15
http://www.edn.com/design/analog/4371297/Design-calculations-for-robust-I2C-
communications
//Disable PIO Controller
PIOB->PIO_PDR |= PIO_PDR_P12 | PIO_PDR_P13;
//Peripheral A selected by default
//Disable the Write Protect Mode
PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN);
//Enable TWI peripheral Clock
PMC->PMC_PCER0 |= PMC_PCER0_PID23;
//Wave Generator - Set TWI Clock to 100kHz
TWI1->TWI_CWGR = 0;
TWI1->TWI_CWGR = TWI_CWGR_CKDIV(1)|TWI_CWGR_CHDIV(0xD4)|TWI_CWGR_CLDIV(0xD4);
//Wave Generator - Set TWI Clock to 400kHz
TWI1->TWI_CWGR = 0;
TWI1->TWI_CWGR = TWI_CWGR_CKDIV(0)|TWI_CWGR_CHDIV(0x65)|TWI_CWGR_CLDIV(0x65);
//SVDIS: Disable the slave mode. MSEN: Enable the master mode.
TWI1->TWI_CR |= TWI_CR_SVDIS | TWI_CR_MSEN;
TWI1->TWI_MMR = 0;
//Write the Device i2c address.
TWI1->TWI_MMR |= TWI_MMR_DADR(0x68);
The following is the code to read a single byte from 0x75 (WHO_AM_I) Register of an I2C device with
device address 0x68 (MPU 6050).
//Set Transfer Direction Bit to 1, and internal address size to 1 byte
TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE | TWI_MMR_MREAD;
//The Internal Address
TWI1->TWI_IADR = TWI_IADR_IADR(0x75);
//Read Single Byte
TWI1->TWI_CR |= TWI_CR_START | TWI_CR_STOP;
//Read Status register, wait until RXRDY is 1
while(!(TWI1->TWI_SR & TWI_SR_RXRDY));
//Read Receive Holding register
data = TWI1->TWI_RHR;
//Read Status Register
while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));
The following is the code to read multiple byte from 0x3B (ACC_X_HIGH_BYTE) Register of an I2C
device with device address 0x68 (MPU 6050).
//The 'device address' is used to access slave, set Transfer Direction Bit to 1
TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE | TWI_MMR_MREAD;
//The Internal Address
TWI1->TWI_IADR = TWI_IADR_IADR(0x3B);
//START
TWI1->TWI_CR |= TWI_CR_START;
int numofbytes = 14;
for(int i = 0; i<numofbytes-1; i++){
//Read Status register, wait until RXRDY is 1
while(!(TWI1->TWI_SR & TWI_SR_RXRDY));
//Read Receive Holding register
data = TWI1->TWI_RHR;
}
//STOP
TWI1->TWI_CR |= TWI_CR_STOP;
//Read Status register, wait until RXRDY is 1
while(!(TWI1->TWI_SR & TWI_SR_RXRDY));
//Read Receive Holding register
data = TWI1->TWI_RHR;
//Read Status Register
while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));*/
The following is the code to write a single byte i.e. 0x00 from 0x00 (PWR_MGMT) Register of an I2C
device with device address 0x68 (MPU 6050).
//The 'device address' is used to access slave, set Transfer Direction Bit to 1
TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE;
TWI1->TWI_MMR &= ~(TWI_MMR_MREAD);
//The Internal Address
TWI1->TWI_IADR = TWI_IADR_IADR(0x00);
//Load data to be sent
TWI1->TWI_THR = 0x00;
//STOP
TWI1->TWI_CR |= TWI_CR_STOP;
//Read Status register, wait until TXRDY is 1
while(!(TWI1->TWI_SR & TWI_SR_TXRDY));
//Read Status Register
while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));
Another thing that I realised, while writing this program was that the Arduino Due was reset after a fixed
interval. I remembered reading about Watchdog Timer while writing code for the TIMER section. So, I
we straight to Section 13 Watchdog Timer (WDT) of the datasheet. After disabling the watchdog timer
the processor doesn’t reset anymore. The following is the line of code to disable Watchdog Timer:
WDT->WDT_MR |= WDT_MR_WDDIS; //Disable the Watchdog Timer
ACTIVATE UART FUNCTION TO COMMUNICATE WITH THE PC
This part is described in the datasheet under Section 34 Universal Asynchronous Receiver Transceiver
(UART). Pin RX0 and TX0 of Arduino Due (pins PA8 and PA9 of sam3x8e) are the UART pins. The
following code initializes the UART communication at 57600 bps. I also posted the code in this forum.
//Enable UART Peripheral Clock
PMC->PMC_PCER0 |= PMC_PCER0_PID8;
//Initialize RX and TX pins
PIOA->PIO_PDR |= PIO_PDR_P8|PIO_PDR_P9;//Peripheral A(RX & TX) are enabled by default
//Disable PDC Channel
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
//Reset and disable receiver and transmitter
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
//Configure Mode
UART->UART_MR |= UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL;//No Parity and normal CH mode
//Configure Rate Generator
UART->UART_BRGR |= UART_BRGR_CD(91); //Baud rate set to 57600 bps
// Configure interrupts
UART->UART_IDR = 0xFFFFFFFF;
UART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
// Enable receiver and transmitter
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
To transmit data, write data to the THR register and wait until the TXRDY bit is set in the UART Status
Register. The following example sends A via UART.
UART->UART_THR = ‘A’; //Write to UART_THR to send ‘A’
while(!(UART->UART_SR & UART_SR_TXRDY)); //Wait till data is sent and THR is empty
ACTIVATE INTERRUPT SERVICE TO ACT WHENEVER PIN STATE TOGGLES
Using interrupts on GPIO pins is quite straight forward. It is described in Section 10 ARM Cortex M3
Processor under subsection: Nested Vectored Interrupt Controller (NVIC). First NVIC needs to be set
up to enable Handler functions. The code to be run in the interrupt is written under the Handler functions.
Here is a link that I referred. Below is the code to enable Edge Detection Interrupt on pin 12 of Arduino
Due. That is pin D8 of sam3x8e (see the pin out).
//Enable Interrupts
PIOD->PIO_IER |= PIO_IER_P8;
//Configure NVIC
NVIC_EnableIRQ(PIOD_IRQn);
//Interrupt Sub Routine
void PIOD_Handler(void){
//code inside interrupt goes here
}

More Related Content

What's hot

Using Ready-for-PIC and SDR Libraries
Using Ready-for-PIC and SDR LibrariesUsing Ready-for-PIC and SDR Libraries
Using Ready-for-PIC and SDR Libraries
Corrado Santoro
 
Microcontroller Instruction Set atmel
Microcontroller Instruction Set atmelMicrocontroller Instruction Set atmel
Microcontroller Instruction Set atmel
Ruderocker Billy
 
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
CODE BLUE
 
Exercises with timers and UART
Exercises with timers and UARTExercises with timers and UART
Exercises with timers and UART
Corrado Santoro
 
Microcontrollers ii
Microcontrollers iiMicrocontrollers ii
Microcontrollers ii
Kumar Kumar
 

What's hot (20)

Ii avr-basics(1)
Ii avr-basics(1)Ii avr-basics(1)
Ii avr-basics(1)
 
89c5131datasheet
89c5131datasheet89c5131datasheet
89c5131datasheet
 
Introduction to Arduino
Introduction to ArduinoIntroduction to Arduino
Introduction to Arduino
 
UART MCU
UART MCUUART MCU
UART MCU
 
Interrupts at AVR
Interrupts at AVRInterrupts at AVR
Interrupts at AVR
 
Arduino cic3
Arduino cic3Arduino cic3
Arduino cic3
 
Part-2: Mastering microcontroller with embedded driver development
Part-2: Mastering microcontroller with embedded driver developmentPart-2: Mastering microcontroller with embedded driver development
Part-2: Mastering microcontroller with embedded driver development
 
AVR_Course_Day6 external hardware interrupts and analogue to digital converter
AVR_Course_Day6 external hardware  interrupts and analogue to digital converterAVR_Course_Day6 external hardware  interrupts and analogue to digital converter
AVR_Course_Day6 external hardware interrupts and analogue to digital converter
 
STM32 Microcontroller Clocks and RCC block
STM32 Microcontroller Clocks and RCC blockSTM32 Microcontroller Clocks and RCC block
STM32 Microcontroller Clocks and RCC block
 
Best-embedded-corporate-training-in-mumbai
Best-embedded-corporate-training-in-mumbaiBest-embedded-corporate-training-in-mumbai
Best-embedded-corporate-training-in-mumbai
 
AVR Fundamentals
AVR FundamentalsAVR Fundamentals
AVR Fundamentals
 
ATmega 16
ATmega 16ATmega 16
ATmega 16
 
Using Ready-for-PIC and SDR Libraries
Using Ready-for-PIC and SDR LibrariesUsing Ready-for-PIC and SDR Libraries
Using Ready-for-PIC and SDR Libraries
 
Microcontroller Instruction Set atmel
Microcontroller Instruction Set atmelMicrocontroller Instruction Set atmel
Microcontroller Instruction Set atmel
 
Lecture7
Lecture7Lecture7
Lecture7
 
Programmable Logic Controller | Ladder Logic diagrams| Block diagram | I/O Mo...
Programmable Logic Controller | Ladder Logic diagrams| Block diagram | I/O Mo...Programmable Logic Controller | Ladder Logic diagrams| Block diagram | I/O Mo...
Programmable Logic Controller | Ladder Logic diagrams| Block diagram | I/O Mo...
 
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
CODE BLUE 2014 : A security assessment study and trial of Tricore-powered aut...
 
Introduction to MPLAB IDE
Introduction to MPLAB IDEIntroduction to MPLAB IDE
Introduction to MPLAB IDE
 
Exercises with timers and UART
Exercises with timers and UARTExercises with timers and UART
Exercises with timers and UART
 
Microcontrollers ii
Microcontrollers iiMicrocontrollers ii
Microcontrollers ii
 

Similar to Itsp documentation quadcopter flight controller based on kalman filters

Microcontroller
MicrocontrollerMicrocontroller
Microcontroller
Spitiq
 
arduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdfarduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdf
ssusere5db05
 
4 IOT 18ISDE712 MODULE 4 IoT Physical Devices and End Point-Aurdino Uno.pdf
4 IOT 18ISDE712  MODULE 4 IoT Physical Devices and End Point-Aurdino  Uno.pdf4 IOT 18ISDE712  MODULE 4 IoT Physical Devices and End Point-Aurdino  Uno.pdf
4 IOT 18ISDE712 MODULE 4 IoT Physical Devices and End Point-Aurdino Uno.pdf
Jayanthi Kannan MK
 

Similar to Itsp documentation quadcopter flight controller based on kalman filters (20)

Avr book
Avr bookAvr book
Avr book
 
Microcontroladores: programación con microcontrolador AVR
Microcontroladores: programación con microcontrolador AVRMicrocontroladores: programación con microcontrolador AVR
Microcontroladores: programación con microcontrolador AVR
 
Microcontroller
MicrocontrollerMicrocontroller
Microcontroller
 
Basics of arduino uno
Basics of arduino unoBasics of arduino uno
Basics of arduino uno
 
Arduino Programming Basic
Arduino Programming BasicArduino Programming Basic
Arduino Programming Basic
 
How to use an Arduino
How to use an ArduinoHow to use an Arduino
How to use an Arduino
 
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
 
Remote ashok
Remote ashokRemote ashok
Remote ashok
 
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
Advanced View of Atmega Microcontroller Projects List - Projects Tutorials Co...
 
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdfAdvanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
 
Embedded system application
Embedded system applicationEmbedded system application
Embedded system application
 
Ardx eg-spar-web-rev10
Ardx eg-spar-web-rev10Ardx eg-spar-web-rev10
Ardx eg-spar-web-rev10
 
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdfAdvanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
Advanced View of Atmega Microcontroller Projects List - ATMega32 AVR.pdf
 
arduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdfarduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdf
 
Arduino course
Arduino courseArduino course
Arduino course
 
publish manual
publish manualpublish manual
publish manual
 
Arduino intro.pptx
Arduino intro.pptxArduino intro.pptx
Arduino intro.pptx
 
4 IOT 18ISDE712 MODULE 4 IoT Physical Devices and End Point-Aurdino Uno.pdf
4 IOT 18ISDE712  MODULE 4 IoT Physical Devices and End Point-Aurdino  Uno.pdf4 IOT 18ISDE712  MODULE 4 IoT Physical Devices and End Point-Aurdino  Uno.pdf
4 IOT 18ISDE712 MODULE 4 IoT Physical Devices and End Point-Aurdino Uno.pdf
 
Contactless digital tachometer using microcontroller
Contactless digital tachometer using microcontroller Contactless digital tachometer using microcontroller
Contactless digital tachometer using microcontroller
 
Fun with arduino
Fun with arduinoFun with arduino
Fun with arduino
 

Recently uploaded

TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Design and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data ScienceDesign and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data Science
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 

Itsp documentation quadcopter flight controller based on kalman filters

  • 1. QUADCOPTER FLIGHT CONTROLLER BASED ON KALMAN FILTERS – ITSP PROJECT DOCUMENTATION I am using Arduino Due in my project. I recently bought it from Amazon. First I decided to start learning arduino due using Arduino IDE. Just for testing, I uploaded an arduino code to extract data out of MPU 6050 using i2c bus and display it through Serial display. On the very first run everything works fine. But when I removed the programming cable and reattached it to the PC and opened the serial monitor, I didn’t get any data. I rechecked everything and still got the same problem. So, I started debugging the code to find if the program is going into infinite loop or something else is wrong. What I found was the code was going into infinite loop in the following line of code Wire.requestFrom(0x68 , 14); while (Wire.available() < 14) Serial.println('.'); //Debug On searching online, I found that many people have been complaining about problems regarding the i2c communication in arduino due. I found many arduino forums discussing the same. I tried to search how to fix the problem but I couldn’t get any proper solution. I found some chunks of code which manipulated register settings which I didn’t understand. Rather than looking up at the internal header files of Arduino, that may be causing the problem, I decided to switch to Atmel studio so that I can understand the register settings and port manipulation better. Also the header files of Arduino IDE contain many lines of codes that are irrelevant for the user and can sometimes cause head-scratching problems like the one above. Arduino Due runs on atsam3x8e or simply sam3x8e, an ARM microprocessor. Unlike AVR processors such as atmega328p (on Adruino Uno), ARM Processors run at 3.3V logic level, are faster and more complex. I downloaded the sam3x8e datasheet from here and an unofficial Arduino Due pin out diagram from here. The official Arduino Due schematic is available here. For my project, the functions I needed to use on due was to: • Find a way to UPLOAD programs from Atmel studio to sam3x8e without using any external programmer • Make sam3x8e run at FULL CLOCK SPEED i.e. 84MHz • Declare Pins as INPUT / OUTPUT and drive the required logic level • Create TIMER functions similar to micros() or delay() (as in Arduino IDE) to create delays of specific time interval • Activate TWI Interface to communicate with I2C sensors • Activate UART Function to communicate with the PC (Serial Monitor of Arduino IDE) • Activate and enable INTERRUPT service to generate interrupt whenever state of pins toggle • Activate ANALOG Pins and use them as INPUT
  • 2. And the following points are why I need them in my project. Some of them are obvious, so I marked them obvious. • UPLOAD: Obvious. • FULL CLOCK SPEED: The faster, the better off course. • INPUT / OUTPUT: Obvious. • TIMER: Obvious. • TWI: Most of the sensors in my project use I2C Interface. • UART: To print data in the Serial Monitor and to talk with the GPS. • INTERRUPT: To read receiver signals while flying. • ANALOG: To determine battery voltage while flying. FIND A WAY TO UPLOAD PROGAMS FROM ATMEL STUDIO WITHOUT EXTERNAL PROGRAMMER Arduino Due has two ports: The Programming Port (ATMEGA16U2) and the Native USB Port (SAM3X). At first, I tried to copy the way Arduino IDE uploads the program to atsam3xe via Programming Port (Atmega16U2). I checked the “Show Verbose Output during Upload” of the Arduino IDE and copied the “Commands and Arguments” to create a new external tool in the Atmel Studio. Although it worked for Arduino Uno and Leonardo (AVR Processor based boards), it didn’t work for Arduino Due. I am not mentioning the exact way I did it, as it didn’t work anyway. What I learnt was: just like ‘avrdude.exe’ is required to program AVR Processors, ‘bossac.exe’ is required to program ARM Processors. As I couldn’t figure out how to upload code via Programming Port, I switched to Native USB Port. I found this website which neatly describes how to upload via Native USB Port. I followed the steps and it worked just fine. MAKE SAM3X8E RUN AT 84MHz On creating a new project on Atmel Studio and selecting device as sam3x8e, in the main program, a function called SystemInit() was called by default. On searching what it does, I found that it configures the system to run at 84MHz. The code in the declaration of SystemInit() is well commented and can be easily understood by referring the datasheet. DECLARE PINS AS OUTPUT AND RUN REQUIRED LOGIC LEVEL Going through the datasheet, under section 31. Parallel Input/Output Controller, I found all the register settings needed to declare a pin as output. To declare pin 13(which is connected to on-board LED) of Arduino Due which is pin B27 of sam3x8e (see the pin out), the code is: PIOB->PIO_PER |= PIO_PER_P27; //PIO Enable Register (not required though) PIOB->PIO_OER |= PIO_OER_P27 ; //Output Enable Register The first line is not required as PIO Controller is enabled by default after reset. But if the pin is configured to work as a peripheral (specially assigned functions), the PIO Controller needs to be enabled first.
  • 3. To drive it high: PIOB->PIO_SODR |= PIO_SODR_P27; //Set Output Data Register To drive it low: PIOB->PIO_CODR |= PIO_CODR_P27; //Clear Output Data Register DECLARE PINS AS INPUT AND READ THEIR LOGIC LEVEL Going further in the same section as above, I found the register settings for declaring pins as input. To declare pin 12 of Arduino Due which is pin D8 of sam3x8e (see the pin out), the code is: PIOD->PIO_PER |= PIO_PER_P8; //PIO Enable Register (not required though) PIOD->PIO_ODR |= PIO_ODR_P8; //Output Disable Register The status of the pin (HIGH or LOW) can be read from the PDSR (Pin Data Status Register). In the following code, the value of state is 1 when pin 12 is HIGH, and 0 when pin 12 is LOW. uint16_t state = (PIOD->PIO_PDSR & PIO_PDSR_P8)>>8; //Read the PIO_PDSR register But the code didn’t work at all. I rechecked the datasheet and found that unlike just declaring pins as input/output, there was an additional instruction that said: “Reading the I/O line levels requires the clock of the PIO controller to be enabled, otherwise PIO_PDSR reads the levels present on the I/O line at the time the clock was disabled”. I searched the datasheet, but didn’t find a clue how to enable the clock. So I advanced further, and while writing the code for UART initialization, I stumbled upon this forum, where someone mentioned about enabling the peripheral clock for UART. So I referred to the Peripheral Identifier section of the datasheet and found a list of PIDs (Peripheral Identifiers) and their corresponding peripheral. I found the peripheral PIOD with PID 14. Then I included the line of code (mentioned below) in my ‘declaring pins as input ‘ program, and pin 12 is successfully declared as input and everything works fine. PCER0 stands for Peripheral Clock Enable Register 0. PMC->PMC_PCER0 |= PMC_PCER0_PID14; //Enable PIOD Clock Afterwards, I found another way to enable Peripheral Clock. PMC->PMC_PCER0 |= (1u<<ID_PIOD); //Enable PIOD Clock I also found that the PCER0 register is actually write protected. Zero needs to be written in the WPEN bit (Write Protect Enable) to disable the Write Protect Mode.
  • 4. But my code still runs without any problem. Maybe the Write Protect Mode was already undone by SystemInit().As my code was working anyway, I didn’t bother to check up. And following is the code to disable the Write Protect Mode. PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN); //Disable the Write Protect Mode CREATE TIMER FUNCTIONS TO CREATE DELAYS OF SPECIFIC INTERVALS In my project, I need a precision of at most 1 us. So I need a clock frequency of at least 1 MHz. There are two sections in the datasheet through which we can create such timers. One is Section 13 RTT (Real Time Timer) and the other is Section 36 TC (Timer Counter). The RTT runs through the SWCLK (SLOW CLOCK) that has a clock frequency of 32.768 kHz, thus, is not suitable for this project. The TC can be made to run from 5 internal clock sources, that are MCK/2, MCK/8, MCK/32, MCK/128 and SWCLK (MCK refers to MAIN CLOCK). As sam3x8e is running at 84 MHz (MCK), the usable frequencies are MCK/2, MCK/8 and MCK/32. I chose to use MCK/8 or 10.5 MHz for my clock frequency. I found this blog which may be useful. The following is the code used for setting up the timer. //Configure PMC //Disable the Write Protect Mode PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN); //Enable TC0 Peripheral Clock PMC->PMC_PCER0 |= PMC_PCER0_PID27; //Disable the Write Protect Mode TC0->TC_WPMR &= ~(TC_WPMR_WPEN); //Set Clock Source to MCK/8 TC0->TC_CHANNEL[0].TC_CMR |= TC_CMR_TCCLKS_TIMER_CLOCK2; //Set Wave select to updown TC0->TC_CHANNEL[0].TC_CMR |= TC_CMR_WAVE | TC_CMR_WAVSEL_UPDOWN; //Enable Clock and trigger to start counter TC0->TC_CHANNEL[0].TC_CCR |= TC_CCR_CLKEN | TC_CCR_SWTRG; The following line of code is used to load the real time counter value onto a variable. //Read current value from Counter Value Register uint32_t counter = TC0->TC_CHANNEL[0].TC_CV; ACTIVATE TWI INTERFACE TO COMMUNICATE WITH I2C SENSORS This part is described in the datasheet under Section 33 Two-Wire Interface (TWI).There are two TWI channels. I’m using the second channel (TWI1) which are pins SDA and SCL of Arduino Due and pins B12 and B13 of sam3x8e (see the pin out). First of all, I programmed the PIO controller to dedicate TWD and TWCK as peripheral lines. Then, enabled the peripheral clock. And set the mode of operation to Master Mode. The steps of using TWI in different modes are neatly displayed in a flowchart at the end of the TWI section.
  • 5. The line of code to set up the speed to 400 kHz actually overwrites the line of code above it which sets the speed to 100 kHz. To run at 100 kHz, just uncomment the line corresponding to 400 kHz. The following is the code to set up the I2C interface at 400 kHz. Note that the prefix “0x” is to represent the number as hexadecimal. https://forum.arduino.cc/index.php?topic=373307.0 https://forum.arduino.cc/index.php?topic=146802.15 http://www.edn.com/design/analog/4371297/Design-calculations-for-robust-I2C- communications //Disable PIO Controller PIOB->PIO_PDR |= PIO_PDR_P12 | PIO_PDR_P13; //Peripheral A selected by default //Disable the Write Protect Mode PMC->PMC_WPMR &= ~(PMC_WPMR_WPEN); //Enable TWI peripheral Clock PMC->PMC_PCER0 |= PMC_PCER0_PID23; //Wave Generator - Set TWI Clock to 100kHz TWI1->TWI_CWGR = 0; TWI1->TWI_CWGR = TWI_CWGR_CKDIV(1)|TWI_CWGR_CHDIV(0xD4)|TWI_CWGR_CLDIV(0xD4); //Wave Generator - Set TWI Clock to 400kHz TWI1->TWI_CWGR = 0; TWI1->TWI_CWGR = TWI_CWGR_CKDIV(0)|TWI_CWGR_CHDIV(0x65)|TWI_CWGR_CLDIV(0x65); //SVDIS: Disable the slave mode. MSEN: Enable the master mode. TWI1->TWI_CR |= TWI_CR_SVDIS | TWI_CR_MSEN; TWI1->TWI_MMR = 0; //Write the Device i2c address. TWI1->TWI_MMR |= TWI_MMR_DADR(0x68); The following is the code to read a single byte from 0x75 (WHO_AM_I) Register of an I2C device with device address 0x68 (MPU 6050). //Set Transfer Direction Bit to 1, and internal address size to 1 byte TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE | TWI_MMR_MREAD; //The Internal Address TWI1->TWI_IADR = TWI_IADR_IADR(0x75); //Read Single Byte TWI1->TWI_CR |= TWI_CR_START | TWI_CR_STOP; //Read Status register, wait until RXRDY is 1 while(!(TWI1->TWI_SR & TWI_SR_RXRDY)); //Read Receive Holding register data = TWI1->TWI_RHR; //Read Status Register while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));
  • 6. The following is the code to read multiple byte from 0x3B (ACC_X_HIGH_BYTE) Register of an I2C device with device address 0x68 (MPU 6050). //The 'device address' is used to access slave, set Transfer Direction Bit to 1 TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE | TWI_MMR_MREAD; //The Internal Address TWI1->TWI_IADR = TWI_IADR_IADR(0x3B); //START TWI1->TWI_CR |= TWI_CR_START; int numofbytes = 14; for(int i = 0; i<numofbytes-1; i++){ //Read Status register, wait until RXRDY is 1 while(!(TWI1->TWI_SR & TWI_SR_RXRDY)); //Read Receive Holding register data = TWI1->TWI_RHR; } //STOP TWI1->TWI_CR |= TWI_CR_STOP; //Read Status register, wait until RXRDY is 1 while(!(TWI1->TWI_SR & TWI_SR_RXRDY)); //Read Receive Holding register data = TWI1->TWI_RHR; //Read Status Register while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));*/ The following is the code to write a single byte i.e. 0x00 from 0x00 (PWR_MGMT) Register of an I2C device with device address 0x68 (MPU 6050). //The 'device address' is used to access slave, set Transfer Direction Bit to 1 TWI1->TWI_MMR |= TWI_MMR_IADRSZ_1_BYTE; TWI1->TWI_MMR &= ~(TWI_MMR_MREAD); //The Internal Address TWI1->TWI_IADR = TWI_IADR_IADR(0x00); //Load data to be sent TWI1->TWI_THR = 0x00; //STOP TWI1->TWI_CR |= TWI_CR_STOP; //Read Status register, wait until TXRDY is 1 while(!(TWI1->TWI_SR & TWI_SR_TXRDY)); //Read Status Register while(!(TWI1->TWI_SR & TWI_SR_TXCOMP));
  • 7. Another thing that I realised, while writing this program was that the Arduino Due was reset after a fixed interval. I remembered reading about Watchdog Timer while writing code for the TIMER section. So, I we straight to Section 13 Watchdog Timer (WDT) of the datasheet. After disabling the watchdog timer the processor doesn’t reset anymore. The following is the line of code to disable Watchdog Timer: WDT->WDT_MR |= WDT_MR_WDDIS; //Disable the Watchdog Timer ACTIVATE UART FUNCTION TO COMMUNICATE WITH THE PC This part is described in the datasheet under Section 34 Universal Asynchronous Receiver Transceiver (UART). Pin RX0 and TX0 of Arduino Due (pins PA8 and PA9 of sam3x8e) are the UART pins. The following code initializes the UART communication at 57600 bps. I also posted the code in this forum. //Enable UART Peripheral Clock PMC->PMC_PCER0 |= PMC_PCER0_PID8; //Initialize RX and TX pins PIOA->PIO_PDR |= PIO_PDR_P8|PIO_PDR_P9;//Peripheral A(RX & TX) are enabled by default //Disable PDC Channel UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; //Reset and disable receiver and transmitter UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS; //Configure Mode UART->UART_MR |= UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL;//No Parity and normal CH mode //Configure Rate Generator UART->UART_BRGR |= UART_BRGR_CD(91); //Baud rate set to 57600 bps // Configure interrupts UART->UART_IDR = 0xFFFFFFFF; UART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME; // Enable receiver and transmitter UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN; To transmit data, write data to the THR register and wait until the TXRDY bit is set in the UART Status Register. The following example sends A via UART. UART->UART_THR = ‘A’; //Write to UART_THR to send ‘A’ while(!(UART->UART_SR & UART_SR_TXRDY)); //Wait till data is sent and THR is empty ACTIVATE INTERRUPT SERVICE TO ACT WHENEVER PIN STATE TOGGLES Using interrupts on GPIO pins is quite straight forward. It is described in Section 10 ARM Cortex M3 Processor under subsection: Nested Vectored Interrupt Controller (NVIC). First NVIC needs to be set up to enable Handler functions. The code to be run in the interrupt is written under the Handler functions. Here is a link that I referred. Below is the code to enable Edge Detection Interrupt on pin 12 of Arduino Due. That is pin D8 of sam3x8e (see the pin out). //Enable Interrupts PIOD->PIO_IER |= PIO_IER_P8;
  • 8. //Configure NVIC NVIC_EnableIRQ(PIOD_IRQn); //Interrupt Sub Routine void PIOD_Handler(void){ //code inside interrupt goes here }