Skip to content
Reza Karbasi edited this page Jul 17, 2016 · 4 revisions

main file

This project is composed of a main.c file and five included library:

  1. asf.h for ATxmega drivers and services

  2. init.h for initiating the microcontroller

  3. nrf24l01.h is a driver for using nRF24l01 wireless IC

  4. controller.h In this library is written a controller and an observer which is used for controlling robot movements

  5. 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));

Checking Wireless Connectivity:

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

State Machine :

This state machine is executed in a sequence which is controlled by data. data is a enum variable. -> Data_Flow

State #1: new_controller_loop

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.

State #2: packing_data

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 ;
   	}

State #3: 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;
		}

State #4: unpacking_data

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 ;
		}

State #5: 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;
		}
	}
}

Interrupt for wireless communication

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 ;	
}

Interrupt for ball detection

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;
	}
}
Clone this wiki locally