-
Notifications
You must be signed in to change notification settings - Fork 0
main.c
This project is composed of a main.c file and five included library:
-
asf.h for ATxmega drivers and services
-
init.h for initiating the microcontroller
-
nrf24l01.h is a driver for using nRF24l01 wireless IC
-
controller.h In this library is written a controller and an observer which is used for controlling robot movements
-
functions.h There is some functions related to :
- Wireless communication
- Monitoring robot state
- Communication with FPGA
- Kick board management
#include <asf.h>
#include "init.h"
#include "nrf24l01.h"
#include "controller.h"
#incude "functions.h"
TODO : All functions should be specified in starting and ending time
Very beginning of main function : Initializing and settings
int main (void)
{
sysclk_init(); //! Initializing system clock
evsys_init(); //! Initializing Event system
pmic_init(); //! Enabling all interrupt levels
port_init(); //! Initializing ports
robot_id_set(); //! Setting robot id
spi_init(); //! Initializing spi
nrf_init(); //! Initializing NRF24l01+
adc_init(); //! Initializing ADC module
tc_init();
rtc_init();
TODO : add Watch-dog if it is needed
Enabling all interrupts:
sei();
while(1)
is composed of a two part. First part is for checking wireless problem. Second part is a state machine which form the main structure of robot's software.
TODO : In first line of
while(1)
we light up green led if KICK_SENSOR detects ball. It should be moved from here.
// complete run time : 23102 clk
while(1)
{
ioport_set_pin_level(LED_GREEN,ioport_get_pin_level(KICK_SENSOR));
WIRLESS_TIMEOUT_TIMER
is a definition for RTC.CNT
which is value of RTC(Real Timer & Counter). The RTC frequency is set to 1.024kHz.So the body of if statement is executed if the value of WIRLESS_TIMEOUT_TIMER
exceeds 10(equals to 10/1024 = 9.76 ms). WIRLESS_TIMEOUT_TIMER
is reset to 0 every time** nRF24l01** receives a packet.
if (WIRLESS_TIMEOUT_TIMER >= 10)
{
cli();
nrf_init () ; //reseting nRF24l01 madule
sei();
free_wheel.wireless_timeout = true ;
WIRLESS_TIMEOUT_TIMER = 0;
data = new_controller_loop ;//for sending free wheel order to fpga
Robot.wrc ++;
}
TODO Check whether it is necessary to turn off interrupts in main loop of program or not
This state machine is executed in a sequence which is controlled by data
. data
is a enum variable. -> Data_Flow
In this casedata == new_controller_loop
.
// run time : about 19115 clk
if (data == new_controller_loop)
{
Timer_show();
Timer_on();
observer();
state_generator();
setpoint_generator() ;
state_feed_back() ;
ocr_change();
float nominal_v[4] ;
float out_l[4];
nominal_v[0]= fabs(u[0][0] / Robot.bat_v.full);
nominal_v[1]= fabs(u[1][0] / Robot.bat_v.full);
nominal_v[2]= fabs(u[2][0] / Robot.bat_v.full);
nominal_v[3]= fabs(u[3][0] / Robot.bat_v.full);
out_l[0] = (454.2 * nominal_v[0] + 326.3) / (pow(nominal_v[0],2) - 8364.0 * nominal_v[0] + 9120.0) * max_ocr * sign(u[0][0]);
out_l[1] = (454.2 * nominal_v[1] + 326.3) / (pow(nominal_v[1],2) - 8364.0 * nominal_v[1] + 9120.0) * max_ocr * sign(u[1][0]);
out_l[2] = (454.2 * nominal_v[2] + 326.3) / (pow(nominal_v[2],2) - 8364.0 * nominal_v[2] + 9120.0) * max_ocr * sign(u[2][0]);
out_l[3] = (454.2 * nominal_v[3] + 326.3) / (pow(nominal_v[3],2) - 8364.0 * nominal_v[3] + 9120.0) * max_ocr * sign(u[3][0]);
Robot.W0_sp.full = out_l[0];
Robot.W1_sp.full = out_l[1];
Robot.W2_sp.full = out_l[2];
Robot.W3_sp.full = out_l[3];
data = packing_data ;
}
1️⃣ First we measure the control loop time with the help of Timer_show() and Timer_on().
2️⃣ Then observer() corrects and filters sensor's data and make them ready for controller.
3️⃣ state_generator() generate new state from new data of sensors which will be used in controller
4️⃣ setpoint_generator() generate new setpoints for controller
5️⃣ state_feed_back() is the controller function
6️⃣ The output of controller (which is voltage) is translated to duty_cycle of PWM signals.
In this state, specification of PWM signals are packed to be send to FPGA. FPGA has the responsibility of driving motors.
//run time : 536 clk
if (data == packing_data)
{
free_wheel_function () ;
data_packing () ;
packet_counter = 0 ;
summer=0;
data = communication ;
}
In this state, packed data is sent from MCU (ATxmega64) to FPGA (SPARTAN3).Also speeds of motors are sent from FPGA to MCU in return.
//run time : 84 clk
if (data == communication)
{
fpga_connection () ;
packet_counter++;
summer += packet_counter;
}
In this state, received data form FPGA is unpacked. This data includes speeds of motors.
// run time : 425 clk
if (data == unpacking_data)
{
data_unpacking () ;
data = other_programs ;
}
All other remaining programs execute in this state:
1️⃣ Red and white LEDs are turned off,which have been turned on in wireless_connection().
2️⃣ read_all_adc() reads analogue values of battery voltage, current sensor outputs and output of temperature sensor of MCU
3️⃣ battery_voltage_update() filters ADC values and converts it to voltage.
4️⃣ boost_buck_manager() manages the kick board. Charges capacitors to 200V and discharges them in chip or kick solenoid for chipping or kicking.
5️⃣ motors_current_check() converts ADC outputs to current values. It also checks motors status whether any of them is in danger of over current.
6️⃣ data_transmission() sends monitoring and debugging data to nRF24l01.
7️⃣current_sensor_offset() drops offset values of current sensors.
// run time : 2 clk
if (data == other_programs)
{
ioport_set_value(LED_RED, low);
ioport_set_value(LED_WHITE, low);
read_all_adc();
battery_voltage_update();
boost_buck_manager();
motors_current_check();
data_transmission();
current_sensor_offset();
data = new_controller_loop;
}
}
}
According to the importance of wireless communication, its code runs in interrupts, whenever nRF24l01 receives a packet from wireless board.
ISR(PORTD_INT0_vect)//PRX IRQ Interrupt Pin
{
wireless_connection();
data = new_controller_loop;//communication;new_controller_loop ;
}
ISR(PORTD_INT1_vect){
if (Robot.KICK>100 && Robot.KICK<=200 && !bbs.kick_flag && !bbs.chip_flag && !bbs.charge_flag)
{
KICK_PERIOD(100);
KICK_DUTY_CYCLE(Robot.KICK - 100);
bbs.lko = sensor_kick ;
KICK_START;
BOOST_BUCK_TIMER = 0;
bbs.kick_flag = true;
}
}