

This project involves designing and building a simple quadcopter using an ATmega64 microcontroller. An MPU6050 sensor sends orientation data via I²C, which is processed by a PID algorithm to maintain stability. PWM signals control four brushless motors through ESCs, while commands are received via a wireless module. Project Description: Building a Simple Quadcopter Using AVR Microcontroller
This project involves designing and building a small quadcopter controlled by an AVR family microcontroller (such as ATmega328P or ATmega32 or atmega64). The quadcopter consists of four brushless DC motors arranged in an “X” or “+” configuration, each driven by an Electronic Speed Controller (ESC). The AVR microcontroller reads data from motion sensors (gyroscope and accelerometer, typically via an MPU6050 module) to maintain stability through a PID control algorithm. User control is achieved through a wireless communication module (e.g., 2.4 GHz RC receiver or NRF24L01). The AVR outputs PWM signals to the ESCs to adjust motor speeds, allowing for lift, movement, and rotation.
Main components:
AVR microcontroller board (e.g., Arduino Nano with ATmega328P)
4 × Brushless DC motors + propellers
4 × ESCs (Electronic Speed Controllers)
MPU6050 (Gyroscope + Accelerometer)
Wireless receiver (e.g., NRF24L01 or RC receiver)
Li-Po battery (e.g., 3S 11.1V)
Quadcopter frame
Key functions:
Sensor data reading via I²C
PID algorithm for flight stability
PWM generation to control motor speeds
Wireless communication for control signals
Outcome: A functional quadcopter capable of stable flight under manual remote control, with the AVR microcontroller handling sensor fusion and motor control.
General Project Overview: At the beginning, we activated the interrupts in the first section. Then, in the init part, we defined the input and output values. In this project, we need interrupts from 0 to 5, which we activate using the ORG directive.

The stack pointer setup, interrupt enabling, and the working mode of the interrupts are defined here. To calculate 250 milliseconds for interrupts 2 and 3, we have set the value of TCNT0 to 6.

General Overview of the Project: At the beginning, we activated the interrupts in the first section. Then, in the initialization part, we defined the input and output values. In this project, we require interrupts from 0 to 5, which are activated using the ORG directive.
The configuration of the stack pointer, enabling of interrupts, and the working mode of the interrupts are defined here. To calculate 250 milliseconds for interrupts 2 and 3, we have set the TCNT0 register to 6.
In this section, we first activated Timer 0 and set the output ports by assigning them a value of 1, indicating output mode. It is worth mentioning that PORTD and PORTE are used in the scoring section to display the position.

We also set registers 17 to 30 to zero so that they can be used in the main code without containing any previous values.

The initial values that the quadcopter must take were stored in the registers, and the interrupts were set.

Interrupts: In interrupts 0 and 1, we performed shift operations (which act as a buffer). In interrupt 0, we used a logical AND with 0, and in interrupt 1, we used a logical OR with 1.

In interrupts 4 and 5, the zero and back interrupts are for direction 1 and 2 speed, and 4 and 5 are for height adjustment:

Timer Zero: In the timer, we have set two registers for the counter, one for every two seconds and the other for every three seconds to back up the relevant interrupts:

In the Check Direction section, the direction for checking the buffer is determined based on the corresponding values:

If it matches the corresponding code, it enters one of the direction rings:

This section is related to speed, so we enter this section of the program every three seconds. If the corresponding password is OK, the processor decides to reduce or increase the speed:

In this section of the code, the speed is increased, which is checked in each section to ensure that the value does not exceed 20, and if it does, it goes to the max speed section to get the value 20:

In this section, it is also used to reduce speed. In each section, it is checked so that the value is not 0 or less than 0. That is why we have given zero in the clear speed section:

In this section, we have used a seven-segment display to display the speed. First, we want to understand that it is a single digit. If it is not, we go to the digit part of the digit. We also want our speed not to be more than twenty. We compare it with 10 digits and go to the label twenty. The possible values are 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20:

Height adjustment: In this section, we compare the code and then, based on the entered code, we understand how much to add to the height:

In the loops, it is checked that if it is greater than 250, it goes to the max high section until the value 250 is set there:

In the tobcd section, we display the height value by first subtracting 100 from the height to obtain the hundreds value. Then the remainder goes to the next section and 10 is subtracted sequentially to obtain the tens value. The remainder is our units value. Then in the phase3 section, by shifting, we display the tens as bcd in the 4 most significant bits of portc and the units as bcd in the 4 least significant bits. We do the same to display the hundreds:


In this section, we have simulated the project in the Proteus program:

And finally, we have implemented part of the project in practice:

Finally, I hope you enjoyed this project. This project was programmed in Dr. Dalir's microprocessor and assembly language course at Khajeh Nasir Tosi University in Tehran. It was a very difficult and breathtaking project that we finally implemented in the JTag programmer. You can download the entire code file in the code section.