Sandwich IoT
Published © GPL3+

Prototype a Robotic Lawn Mower-Tuya Developer

Getting your lawn spruced up in the summer sun is often a dreaded chore for homeowners.

BeginnerFull instructions provided8 hours483
Prototype a Robotic Lawn Mower-Tuya Developer

Things used in this project

Hardware components

Network module
×1
Battery
×1
Buck converter
×1
Geared motor
×1
Motor driver
×1
Motor
×1
Electronic speed controller (ESC)
×1
Servo
×1
Global navigation satellite system (GNSS)
×1
Electronic compass sensor
×1

Story

Read more

Code

Code snippet #11

Plain text
int e[4]={0},e1[4]={0},e2[4]={0}; // PID offset
float uk[4]={0.0},uk1[4]={0.0},duk[4]={0.0}; // PID output
float Kp=0.8,Ki=0.3,Kd=0.9; // PID control factors.
int out[4] = {0};

static void forward_correction(uint32_t *pulse_num, uint32_t *pulse_num_old, uint32_t standard_increment)
{
    uint8_t i = 0;
	    
	for(i = 0;i < 4;i++) {
		    e[i] = standard_increment - (pulse_num[i] - pulse_num_old[i]);
			duk[i] = (Kp*(e[i]-e1[i])+Ki*e[i])/100;
			uk[i] = uk1[i] + duk[i];
			out[i] = (int)uk[i];
			uk1[i] = uk[i];
			e2[i] = e1[i];
			e1[i] = e[i];
		    single_motor_speed_set(i, (uint16_t)(200+(out[i]*5)));
    }
    return;
}

Code snippet #12

Plain text
int e[4]={0},e1[4]={0},e2[4]={0}; // PID offset
float uk[4]={0.0},uk1[4]={0.0},duk[4]={0.0}; // PID output
float Kp=0.8,Ki=0.3,Kd=0.9; // PID control factors.
int out[4] = {0};

static void forward_correction(uint32_t *pulse_num, uint32_t *pulse_num_old, uint32_t standard_increment)
{
    uint8_t i = 0;
	    
	for(i = 0;i < 4;i++) {
		    e[i] = standard_increment - (pulse_num[i] - pulse_num_old[i]);
			duk[i] = (Kp*(e[i]-e1[i])+Ki*e[i])/100;
			uk[i] = uk1[i] + duk[i];
			out[i] = (int)uk[i];
			uk1[i] = uk[i];
			e2[i] = e1[i];
			e1[i] = e[i];
		    single_motor_speed_set(i, (uint16_t)(200+(out[i]*5)));
    }
    return;
}

Code snippet #13

Plain text
void movement_logic_handle(void)
{   
    MOVE_STATE_T *p = NULL;
	p = &move_state;
	uint8_t i = 0;
	MOVING_DIRECTION turning_state;
	  
    switch(p->todo_type) {
		
     ......
	case on_the_move:
			  
	    if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
		    for(i = 0;i < 4;i++) {
			    pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];							
			}

			forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);
						 
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse_old[i] = p->encoder_pulse[i];							
			}				
			forward_sampling_time_flag = 0;
	    }
        forward_sampling_time_flag++;
        
        todo_judge();
					
    break;	
		......
		default:
				break;		
		}
	
}

Code snippet #14

Plain text
void movement_logic_handle(void)
{   
    MOVE_STATE_T *p = NULL;
	p = &move_state;
	uint8_t i = 0;
	MOVING_DIRECTION turning_state;
	  
    switch(p->todo_type) {
		
     ......
	case on_the_move:
			  
	    if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
		    for(i = 0;i < 4;i++) {
			    pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];							
			}

			forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);
						 
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse_old[i] = p->encoder_pulse[i];							
			}				
			forward_sampling_time_flag = 0;
	    }
        forward_sampling_time_flag++;
        
        todo_judge();
					
    break;	
		......
		default:
				break;		
		}
	
}

Code snippet #15

Plain text
static void todo_judge(void)
{
      MOVE_STATE_T *p = NULL;
	  p = &move_state;
	  
    switch(p->run_step_flag) {
			
		case length_right:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
						if((p->current_angle + 900) > 3600) {
								p->target_angle = p->current_angle + 900 - 3600;
						}else{
								p->target_angle = p->current_angle + 900;
						}

						change_to_do(turning);
						p->run_step_flag = width_right;

				}
		    break;
		case width_right:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
						if((p->current_angle + 900) > 3600) {
								p->target_angle = p->current_angle + 900 - 3600;
						}else{
								p->target_angle = p->current_angle + 900;
						}
						change_to_do(turning);
						p->run_step_flag = length_left;
						width_remain_mm -= 100;

				}
		    break;
		case length_left:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
						if(p->current_angle < 900) {
								p->target_angle = 3600 - (900 - p->current_angle);
						}else{
								p->target_angle = p->current_angle - 900;
						}
						change_to_do(turning);
						p->run_step_flag = width_left;

				}
		    break;
		case width_left:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
						if(p->current_angle < 900) {
								p->target_angle = 3600 - (900 - p->current_angle);
						}else{
								p->target_angle = p->current_angle - 900;
						}
						change_to_do(turning);
						p->run_step_flag = length_right;
						width_remain_mm -= 100;
						
				}
		    break;
		default:
				break;
		}
		
		if(width_remain_mm <= 0) {
            change_to_do(to_stop);
			move_state.bow_mode_switch = pdFALSE;
		}

}

Code snippet #16

Plain text
static void todo_judge(void)
{
      MOVE_STATE_T *p = NULL;
	  p = &move_state;
	  
    switch(p->run_step_flag) {
			
		case length_right:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
						if((p->current_angle + 900) > 3600) {
								p->target_angle = p->current_angle + 900 - 3600;
						}else{
								p->target_angle = p->current_angle + 900;
						}

						change_to_do(turning);
						p->run_step_flag = width_right;

				}
		    break;
		case width_right:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
						if((p->current_angle + 900) > 3600) {
								p->target_angle = p->current_angle + 900 - 3600;
						}else{
								p->target_angle = p->current_angle + 900;
						}
						change_to_do(turning);
						p->run_step_flag = length_left;
						width_remain_mm -= 100;

				}
		    break;
		case length_left:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
						if(p->current_angle < 900) {
								p->target_angle = 3600 - (900 - p->current_angle);
						}else{
								p->target_angle = p->current_angle - 900;
						}
						change_to_do(turning);
						p->run_step_flag = width_left;

				}
		    break;
		case width_left:
			  if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
						if(p->current_angle < 900) {
								p->target_angle = 3600 - (900 - p->current_angle);
						}else{
								p->target_angle = p->current_angle - 900;
						}
						change_to_do(turning);
						p->run_step_flag = length_right;
						width_remain_mm -= 100;
						
				}
		    break;
		default:
				break;
		}
		
		if(width_remain_mm <= 0) {
            change_to_do(to_stop);
			move_state.bow_mode_switch = pdFALSE;
		}

}

Code snippet #17

Plain text
void move_control_task(void *pvParameters)
{   

      float_xyz Mag_angle;
	  uint8_t test_flag = 50;
	  vTaskDelay(200);
	  QMC_Init();
	  QMC5883L_GetAngle(&Mag_angle);
	  move_state.current_angle = (int16_t)Mag_angle.x;
	  vTaskDelay(500);

      while(1) {	
        
          if(test_flag){
		      vTaskDelay(20);
	          test_flag--;
		  }else if(test_flag == 0) {
		      vTaskDelay(20);
		      movement_logic_handle();
		  }
		  QMC5883L_GetAngle(&Mag_angle);
          move_state.current_angle = (int16_t)Mag_angle.x;
    }
}

Code snippet #18

Plain text
void move_control_task(void *pvParameters)
{   

      float_xyz Mag_angle;
	  uint8_t test_flag = 50;
	  vTaskDelay(200);
	  QMC_Init();
	  QMC5883L_GetAngle(&Mag_angle);
	  move_state.current_angle = (int16_t)Mag_angle.x;
	  vTaskDelay(500);

      while(1) {	
        
          if(test_flag){
		      vTaskDelay(20);
	          test_flag--;
		  }else if(test_flag == 0) {
		      vTaskDelay(20);
		      movement_logic_handle();
		  }
		  QMC5883L_GetAngle(&Mag_angle);
          move_state.current_angle = (int16_t)Mag_angle.x;
    }
}

Code snippet #19

Plain text
static MOVING_DIRECTION angle_correction(void)
{
    int16_t target,current = 0;
	  target = move_state.target_angle;
	  current = move_state.current_angle;
    if(target < current) {
			  if(current - target <= 20) {
					  return forward;
				}
		    if(current - target <= 1800) {
				    return left;
				}else{
				    return right;
				}
		}else if(target > current) {
				if(target - current <= 20) {
				    return forward;
				}
		    if(target - current <= 1800) {
				    return right;
				}else{
				    return left;
				}
		}else if(current == target) {
		    return forward;
		}
}

void movement_logic_handle(void)
{   
    MOVE_STATE_T *p = NULL;
	p = &move_state;
	uint8_t i = 0;
	MOVING_DIRECTION turning_state;
	  
    switch(p->todo_type) {
		
     ......
	case on_the_move:
			  
	    if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
		    for(i = 0;i < 4;i++) {
			    pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];							
			}

			forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);
						 
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse_old[i] = p->encoder_pulse[i];							
			}				
			forward_sampling_time_flag = 0;
	    }
        forward_sampling_time_flag++;
        
        todo_judge();
					
        break;
    case turning: 
			
	    turning_state = angle_correction();

        if(turning_state == right) {
	        car_full_turn(right,150);
			turning_sampling_time_flag = 0;
        }else if(turning_state == left) {
		    car_full_turn(left,150);
		    turning_sampling_time_flag = 0;
		}else if(turning_state == forward) {
		    car_moving(stop,0);
		    turning_sampling_time_flag++;
		}        				 
				
		if(turning_sampling_time_flag >= 25) {
		    p->todo_type = on_the_move;
		    car_moving(forward,200);
			forward_sampling_time_flag = 0;
			turning_sampling_time_flag = 0;
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse[i] = 0;
                p->encoder_pulse_old[i] = 0;							
			}
		}

        break;
		......
		default:
				break;		
		}
	
}

Code snippet #20

Plain text
static MOVING_DIRECTION angle_correction(void)
{
    int16_t target,current = 0;
	  target = move_state.target_angle;
	  current = move_state.current_angle;
    if(target < current) {
			  if(current - target <= 20) {
					  return forward;
				}
		    if(current - target <= 1800) {
				    return left;
				}else{
				    return right;
				}
		}else if(target > current) {
				if(target - current <= 20) {
				    return forward;
				}
		    if(target - current <= 1800) {
				    return right;
				}else{
				    return left;
				}
		}else if(current == target) {
		    return forward;
		}
}

void movement_logic_handle(void)
{   
    MOVE_STATE_T *p = NULL;
	p = &move_state;
	uint8_t i = 0;
	MOVING_DIRECTION turning_state;
	  
    switch(p->todo_type) {
		
     ......
	case on_the_move:
			  
	    if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
		    for(i = 0;i < 4;i++) {
			    pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];							
			}

			forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);
						 
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse_old[i] = p->encoder_pulse[i];							
			}				
			forward_sampling_time_flag = 0;
	    }
        forward_sampling_time_flag++;
        
        todo_judge();
					
        break;
    case turning: 
			
	    turning_state = angle_correction();

        if(turning_state == right) {
	        car_full_turn(right,150);
			turning_sampling_time_flag = 0;
        }else if(turning_state == left) {
		    car_full_turn(left,150);
		    turning_sampling_time_flag = 0;
		}else if(turning_state == forward) {
		    car_moving(stop,0);
		    turning_sampling_time_flag++;
		}        				 
				
		if(turning_sampling_time_flag >= 25) {
		    p->todo_type = on_the_move;
		    car_moving(forward,200);
			forward_sampling_time_flag = 0;
			turning_sampling_time_flag = 0;
			for(i = 0;i < 4;i++) {
			    p->encoder_pulse[i] = 0;
                p->encoder_pulse_old[i] = 0;							
			}
		}

        break;
		......
		default:
				break;		
		}
	
}

Code snippet #3

Plain text
#define MOTOR_PORT_1                        GPIOA
#define MOTOR_PIN_1                         GPIO_PIN_15
#define MOTOR_PORT_1_P                      GPIOD
#define MOTOR_PIN_1_P                       GPIO_PIN_0
#define MOTOR_PORT_1_N                      GPIOD
#define MOTOR_PIN_1_N                       GPIO_PIN_7

#define MOTOR_PORT_2                        GPIOB
#define MOTOR_PIN_2                         GPIO_PIN_9
#define MOTOR_PORT_2_P                      GPIOD
#define MOTOR_PIN_2_P                       GPIO_PIN_1
#define MOTOR_PORT_2_N                      GPIOD
#define MOTOR_PIN_2_N                       GPIO_PIN_2


#define MOTOR_PORT_3                        GPIOB
#define MOTOR_PIN_3                         GPIO_PIN_10
#define MOTOR_PORT_3_P                      GPIOD
#define MOTOR_PIN_3_P                       GPIO_PIN_3
#define MOTOR_PORT_3_N                      GPIOD
#define MOTOR_PIN_3_N                       GPIO_PIN_4


#define MOTOR_PORT_4                        GPIOB
#define MOTOR_PIN_4                         GPIO_PIN_11
#define MOTOR_PORT_4_P                      GPIOD
#define MOTOR_PIN_4_P                       GPIO_PIN_8
#define MOTOR_PORT_4_N                      GPIOD
#define MOTOR_PIN_4_N                       GPIO_PIN_9 

#define MOTOR_CHANNEL_1                     TIMER_CH_0
#define MOTOR_CHANNEL_2                     TIMER_CH_1
#define MOTOR_CHANNEL_3                     TIMER_CH_2
#define MOTOR_CHANNEL_4                     TIMER_CH_3

#define SERVO_PORT_1                        GPIOC
#define SERVO_PIN_1                         GPIO_PIN_6

#define SERVO_PORT_2                        GPIOC
#define SERVO_PIN_2                         GPIO_PIN_7

#define BLADE_MOTOR_PORT                    GPIOC
#define BLADE_MOTOR_PIN                     GPIO_PIN_8

Code snippet #21

Plain text
void blade_position_set(BLADE_POSITION value)
{
    switch(value) {
			
		case low:  
					
		    timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,3100);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,3000);			
				break;
		
		case medium:
			
		    timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2800);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2700);	
				break;
		
		case high:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2600);
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2500);
				break;
		
		default:
				break;			
		}
}

Code snippet #22

Plain text
void blade_position_set(BLADE_POSITION value)
{
    switch(value) {
			
		case low:  
					
		    timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,3100);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,3000);			
				break;
		
		case medium:
			
		    timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2800);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2700);	
				break;
		
		case high:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2600);
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2500);
				break;
		
		default:
				break;			
		}
}

Code snippet #23

Plain text
void blade_speed_set(BLADE_SPEED speed)
{
    switch(speed) {
		
		case init:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1500);					
			  break;
			
		case off:
			
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,0);
			  break;
		
		case low_speed:  
					
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1800);	
				break;
		
		case medium_speed:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1900);		
				break;
		
		case high_speed:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,2000);	
				break;
		
		default:
				break;			
		}
}

Code snippet #24

Plain text
void blade_speed_set(BLADE_SPEED speed)
{
    switch(speed) {
		
		case init:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1500);					
			  break;
			
		case off:
			
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,0);
			  break;
		
		case low_speed:  
					
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1800);	
				break;
		
		case medium_speed:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1900);		
				break;
		
		case high_speed:
			
			  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,2000);	
				break;
		
		default:
				break;			
		}
}

Code snippet #25

Plain text
void uart_init(void)
{   
	  /* USART interrupt configuration */
    nvic_irq_enable(USART0_IRQn, 0, 0);
    nvic_irq_enable(USART1_IRQn, 1, 1);

    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);
	
    /* connect port to USART0_Tx */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);

    /* connect port to USART0_Rx */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
	
    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    /* USART configure */
    usart_deinit(USART0);
    usart_baudrate_set(USART0,115200U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
		
		/* enable USART clock */
    rcu_periph_clock_enable(RCU_USART1);
	
    /* connect port to USART0_Tx */
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_5);

    /* connect port to USART0_Rx */
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_6);
	
    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_5);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);

    /* USART configure */
    usart_deinit(USART1);
    usart_baudrate_set(USART1,9600U);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
    usart_enable(USART1);
		
		/* enable USART0 receive interrupt */
    usart_interrupt_enable(USART0, USART_INT_RBNE);
	
	  /* enable USART1 receive interrupt */
    usart_interrupt_enable(USART1, USART_INT_RBNE);
}

Code snippet #26

Plain text
void uart_init(void)
{   
	  /* USART interrupt configuration */
    nvic_irq_enable(USART0_IRQn, 0, 0);
    nvic_irq_enable(USART1_IRQn, 1, 1);

    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);
	
    /* connect port to USART0_Tx */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);

    /* connect port to USART0_Rx */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
	
    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    /* USART configure */
    usart_deinit(USART0);
    usart_baudrate_set(USART0,115200U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
		
		/* enable USART clock */
    rcu_periph_clock_enable(RCU_USART1);
	
    /* connect port to USART0_Tx */
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_5);

    /* connect port to USART0_Rx */
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_6);
	
    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_5);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);

    /* USART configure */
    usart_deinit(USART1);
    usart_baudrate_set(USART1,9600U);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
    usart_enable(USART1);
		
		/* enable USART0 receive interrupt */
    usart_interrupt_enable(USART0, USART_INT_RBNE);
	
	  /* enable USART1 receive interrupt */
    usart_interrupt_enable(USART1, USART_INT_RBNE);
}

Code snippet #27

Plain text
#define USART_FH_len 6  // The length of the header.
char USART_FH[USART_FH_len]={'$','G','N','G','G','A'}; // Header
#define USART_FT_len 2  // The length of the trailer.
uint8_t USART_FT[USART_FT_len]={0X0D,0X0A}; // Frame trailer

uint8_t data_buf[128] = {0};
uint8_t rx_buf[128] = {0};
uint8_t buff_len = 0;

void USART1_IRQHandler(void)
{
    if((RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)) && 
       (RESET != usart_flag_get(USART1, USART_FLAG_RBNE))){	
			 
        rx_buf[buff_len++] = (uint8_t)usart_data_receive(USART1);

		if(rx_buf[0] != USART_FH[0]) {
		    rx_buf[0] = 0;
		    buff_len = 0;
	    }

		if(buff_len >= USART_FH_len) {

		    if(strncmp((char*)rx_buf,USART_FH,USART_FH_len) == 0) {
			    if(strncmp(&rx_buf[buff_len-2],(char*)USART_FT,USART_FT_len) == 0) {
				    memcpy(data_buf,rx_buf,buff_len);
					memset(rx_buf,0,buff_len);
					buff_len = 0;
				}
        }else {
		    memset(rx_buf,0,USART_FH_len);
			buff_len = 0;
		}
	}
  }
}

void gps_data_task(void *pvParameters)
{
    MAP_POINT_t *p;
	p = &map_point[point_1];
    uint8_t data_len = 0;
    while(1) {
        vTaskDelay(100);
			
        data_len = strlen((char*)data_buf);
        if(data_len != 0){
	        gps_data_pick(point_1, data_buf, data_len);
		    memset(data_buf,0,data_len);
		}
    }
}

Code snippet #28

Plain text
#define USART_FH_len 6  // The length of the header.
char USART_FH[USART_FH_len]={'$','G','N','G','G','A'}; // Header
#define USART_FT_len 2  // The length of the trailer.
uint8_t USART_FT[USART_FT_len]={0X0D,0X0A}; // Frame trailer

uint8_t data_buf[128] = {0};
uint8_t rx_buf[128] = {0};
uint8_t buff_len = 0;

void USART1_IRQHandler(void)
{
    if((RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)) && 
       (RESET != usart_flag_get(USART1, USART_FLAG_RBNE))){	
			 
        rx_buf[buff_len++] = (uint8_t)usart_data_receive(USART1);

		if(rx_buf[0] != USART_FH[0]) {
		    rx_buf[0] = 0;
		    buff_len = 0;
	    }

		if(buff_len >= USART_FH_len) {

		    if(strncmp((char*)rx_buf,USART_FH,USART_FH_len) == 0) {
			    if(strncmp(&rx_buf[buff_len-2],(char*)USART_FT,USART_FT_len) == 0) {
				    memcpy(data_buf,rx_buf,buff_len);
					memset(rx_buf,0,buff_len);
					buff_len = 0;
				}
        }else {
		    memset(rx_buf,0,USART_FH_len);
			buff_len = 0;
		}
	}
  }
}

void gps_data_task(void *pvParameters)
{
    MAP_POINT_t *p;
	p = &map_point[point_1];
    uint8_t data_len = 0;
    while(1) {
        vTaskDelay(100);
			
        data_len = strlen((char*)data_buf);
        if(data_len != 0){
	        gps_data_pick(point_1, data_buf, data_len);
		    memset(data_buf,0,data_len);
		}
    }
}

Code snippet #4

Plain text
#define MOTOR_PORT_1                        GPIOA
#define MOTOR_PIN_1                         GPIO_PIN_15
#define MOTOR_PORT_1_P                      GPIOD
#define MOTOR_PIN_1_P                       GPIO_PIN_0
#define MOTOR_PORT_1_N                      GPIOD
#define MOTOR_PIN_1_N                       GPIO_PIN_7

#define MOTOR_PORT_2                        GPIOB
#define MOTOR_PIN_2                         GPIO_PIN_9
#define MOTOR_PORT_2_P                      GPIOD
#define MOTOR_PIN_2_P                       GPIO_PIN_1
#define MOTOR_PORT_2_N                      GPIOD
#define MOTOR_PIN_2_N                       GPIO_PIN_2


#define MOTOR_PORT_3                        GPIOB
#define MOTOR_PIN_3                         GPIO_PIN_10
#define MOTOR_PORT_3_P                      GPIOD
#define MOTOR_PIN_3_P                       GPIO_PIN_3
#define MOTOR_PORT_3_N                      GPIOD
#define MOTOR_PIN_3_N                       GPIO_PIN_4


#define MOTOR_PORT_4                        GPIOB
#define MOTOR_PIN_4                         GPIO_PIN_11
#define MOTOR_PORT_4_P                      GPIOD
#define MOTOR_PIN_4_P                       GPIO_PIN_8
#define MOTOR_PORT_4_N                      GPIOD
#define MOTOR_PIN_4_N                       GPIO_PIN_9 

#define MOTOR_CHANNEL_1                     TIMER_CH_0
#define MOTOR_CHANNEL_2                     TIMER_CH_1
#define MOTOR_CHANNEL_3                     TIMER_CH_2
#define MOTOR_CHANNEL_4                     TIMER_CH_3

#define SERVO_PORT_1                        GPIOC
#define SERVO_PIN_1                         GPIO_PIN_6

#define SERVO_PORT_2                        GPIOC
#define SERVO_PIN_2                         GPIO_PIN_7

#define BLADE_MOTOR_PORT                    GPIOC
#define BLADE_MOTOR_PIN                     GPIO_PIN_8

Code snippet #5

Plain text
void servo_motor_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
	
	  /*Configure PD1~8 Output motor Positive and Negative pin to drive wheels_1~4*/
	  gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
	
    /*Configure PA15(TIMER1_CH0) Output PWM pulse to drive wheels_1*/
    gpio_mode_set(MOTOR_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_1);
    gpio_output_options_set(MOTOR_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1);
    gpio_af_set(MOTOR_PORT_1, GPIO_AF_1, MOTOR_PIN_1);

    /*Configure PB9(TIMER1_CH1) Output PWM pulse to drive wheels_2*/
    gpio_mode_set(MOTOR_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_2);
    gpio_output_options_set(MOTOR_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_2);
    gpio_af_set(MOTOR_PORT_2, GPIO_AF_1, MOTOR_PIN_2);

    /*Configure PB10(TIMER1_CH2) Output PWM pulse to drive wheels_3*/
    gpio_mode_set(MOTOR_PORT_3, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_3);
    gpio_output_options_set(MOTOR_PORT_3, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_3);
    gpio_af_set(MOTOR_PORT_3, GPIO_AF_1, MOTOR_PIN_3);

    /*Configure PB11(TIMER1_CH3) Output PWM pulse to drive wheels_4*/
    gpio_mode_set(MOTOR_PORT_4, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_4);
    gpio_output_options_set(MOTOR_PORT_4, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_4);
    gpio_af_set(MOTOR_PORT_4, GPIO_AF_1, MOTOR_PIN_4);

    /*Configure PC6(TIMER2_CH0) Output PWM pulse to drive servo no.1*/
    gpio_mode_set(SERVO_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_1);
    gpio_output_options_set(SERVO_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_1);
    gpio_af_set(SERVO_PORT_1, GPIO_AF_2, SERVO_PIN_1);
		
    /*Configure PC7(TIMER2_CH1) Output PWM pulse to drive servo no.2*/
    gpio_mode_set(SERVO_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_2);
    gpio_output_options_set(SERVO_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_2);
    gpio_af_set(SERVO_PORT_2, GPIO_AF_2, SERVO_PIN_2);
		
	/*Configure PC8(TIMER2_CH2) Output PWM pulse to drive blade motor*/
    gpio_mode_set(BLADE_MOTOR_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, BLADE_MOTOR_PIN);
    gpio_output_options_set(BLADE_MOTOR_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,BLADE_MOTOR_PIN);
    gpio_af_set(BLADE_MOTOR_PORT, GPIO_AF_2, BLADE_MOTOR_PIN);
		
    timer_config();

}

void timer_config(void)
{
    uint16_t i = 0;
	
    /* TIMER1 configuration: generate PWM signals with different duty cycles:
       TIMER1CLK = SystemCoreClock / 120 = 1MHz */
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER1);
    rcu_periph_clock_enable(RCU_TIMER2);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
    timer_struct_para_init(&timer_initpara);
    timer_deinit(TIMER1);
    timer_deinit(TIMER2);

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 500; /* 500*(1/1MHZ) = 500us */
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1,&timer_initpara);

    /* TIMER2 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 20000; /* 20000*(1/1MHZ) = 20ms */
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    timer_channel_output_struct_para_init(&timer_ocintpara);
    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

    for(i = 0; i < 4; i++) {
			
        timer_channel_output_config(TIMER1,i,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER1,i,0);
        timer_channel_output_mode_config(TIMER1,i,TIMER_OC_MODE_PWM0);
        timer_channel_output_shadow_config(TIMER1,i,TIMER_OC_SHADOW_DISABLE);
    }

		for(i = 0; i < 3; i++) {
			
        timer_channel_output_config(TIMER2,i,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,i,0);
        timer_channel_output_mode_config(TIMER2,i,TIMER_OC_MODE_PWM0);
        timer_channel_output_shadow_config(TIMER2,i,TIMER_OC_SHADOW_DISABLE);
    }

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER1);
    timer_auto_reload_shadow_enable(TIMER2);

    /* TIMER enable */
    timer_enable(TIMER1);
    timer_enable(TIMER2);
}

Code snippet #6

Plain text
void servo_motor_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
	
	  /*Configure PD1~8 Output motor Positive and Negative pin to drive wheels_1~4*/
	  gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
	
    /*Configure PA15(TIMER1_CH0) Output PWM pulse to drive wheels_1*/
    gpio_mode_set(MOTOR_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_1);
    gpio_output_options_set(MOTOR_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1);
    gpio_af_set(MOTOR_PORT_1, GPIO_AF_1, MOTOR_PIN_1);

    /*Configure PB9(TIMER1_CH1) Output PWM pulse to drive wheels_2*/
    gpio_mode_set(MOTOR_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_2);
    gpio_output_options_set(MOTOR_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_2);
    gpio_af_set(MOTOR_PORT_2, GPIO_AF_1, MOTOR_PIN_2);

    /*Configure PB10(TIMER1_CH2) Output PWM pulse to drive wheels_3*/
    gpio_mode_set(MOTOR_PORT_3, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_3);
    gpio_output_options_set(MOTOR_PORT_3, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_3);
    gpio_af_set(MOTOR_PORT_3, GPIO_AF_1, MOTOR_PIN_3);

    /*Configure PB11(TIMER1_CH3) Output PWM pulse to drive wheels_4*/
    gpio_mode_set(MOTOR_PORT_4, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_4);
    gpio_output_options_set(MOTOR_PORT_4, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_4);
    gpio_af_set(MOTOR_PORT_4, GPIO_AF_1, MOTOR_PIN_4);

    /*Configure PC6(TIMER2_CH0) Output PWM pulse to drive servo no.1*/
    gpio_mode_set(SERVO_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_1);
    gpio_output_options_set(SERVO_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_1);
    gpio_af_set(SERVO_PORT_1, GPIO_AF_2, SERVO_PIN_1);
		
    /*Configure PC7(TIMER2_CH1) Output PWM pulse to drive servo no.2*/
    gpio_mode_set(SERVO_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_2);
    gpio_output_options_set(SERVO_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_2);
    gpio_af_set(SERVO_PORT_2, GPIO_AF_2, SERVO_PIN_2);
		
	/*Configure PC8(TIMER2_CH2) Output PWM pulse to drive blade motor*/
    gpio_mode_set(BLADE_MOTOR_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, BLADE_MOTOR_PIN);
    gpio_output_options_set(BLADE_MOTOR_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,BLADE_MOTOR_PIN);
    gpio_af_set(BLADE_MOTOR_PORT, GPIO_AF_2, BLADE_MOTOR_PIN);
		
    timer_config();

}

void timer_config(void)
{
    uint16_t i = 0;
	
    /* TIMER1 configuration: generate PWM signals with different duty cycles:
       TIMER1CLK = SystemCoreClock / 120 = 1MHz */
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER1);
    rcu_periph_clock_enable(RCU_TIMER2);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
    timer_struct_para_init(&timer_initpara);
    timer_deinit(TIMER1);
    timer_deinit(TIMER2);

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 500; /* 500*(1/1MHZ) = 500us */
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1,&timer_initpara);

    /* TIMER2 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 20000; /* 20000*(1/1MHZ) = 20ms */
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    timer_channel_output_struct_para_init(&timer_ocintpara);
    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

    for(i = 0; i < 4; i++) {
			
        timer_channel_output_config(TIMER1,i,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER1,i,0);
        timer_channel_output_mode_config(TIMER1,i,TIMER_OC_MODE_PWM0);
        timer_channel_output_shadow_config(TIMER1,i,TIMER_OC_SHADOW_DISABLE);
    }

		for(i = 0; i < 3; i++) {
			
        timer_channel_output_config(TIMER2,i,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,i,0);
        timer_channel_output_mode_config(TIMER2,i,TIMER_OC_MODE_PWM0);
        timer_channel_output_shadow_config(TIMER2,i,TIMER_OC_SHADOW_DISABLE);
    }

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER1);
    timer_auto_reload_shadow_enable(TIMER2);

    /* TIMER enable */
    timer_enable(TIMER1);
    timer_enable(TIMER2);
}

Code snippet #7

Plain text
void car_moving(MOVING_DIRECTION direction, uint16_t speed_value)
{
    uint8_t i;
    switch(direction) {
			
	case forward:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
		for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }
		break;
	case right:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);		
		
		//Since the two sets of wheels on the right are always faster than the left in the actual commissioning process, 60 is added to compensate
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value + 60);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value + 60);
				
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value);	
		break;
	case left:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);	

		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value);
		
        timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value + 50);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value + 50);
		break;
	case backward:
			
	    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_set(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
		for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }	
		break;
	case stop:
			
	    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
	    for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }
	    break;
	default:
				break;
		}
}

Code snippet #8

Plain text
void car_moving(MOVING_DIRECTION direction, uint16_t speed_value)
{
    uint8_t i;
    switch(direction) {
			
	case forward:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
		for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }
		break;
	case right:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);		
		
		//Since the two sets of wheels on the right are always faster than the left in the actual commissioning process, 60 is added to compensate
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value + 60);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value + 60);
				
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value);	
		break;
	case left:
			
	    gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);	

		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value);
		
        timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value + 50);
		timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value + 50);
		break;
	case backward:
			
	    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_set(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
		for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }	
		break;
	case stop:
			
	    gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
		gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
		
	    for(i = 0; i < 4; i++) {
		    timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
        }
	    break;
	default:
				break;
		}
}

Code snippet #9

Plain text
void movement_system_init(void)
{
	  rcu_periph_clock_enable(RCU_SYSCFG);
	
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
	  nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN0);
	  exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_0);
	
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
	  nvic_irq_enable(EXTI1_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN1);
	  exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_1);

	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
	  nvic_irq_enable(EXTI2_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN2);
	  exti_init(EXTI_2, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_2);
		
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
	  nvic_irq_enable(EXTI3_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN3);
	  exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_3);
}
	
void EXTI0_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_0)){
	        move_state.encoder_pulse[0]++;		
    }
    exti_interrupt_flag_clear(EXTI_0);
}

void EXTI1_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_1)){
	        move_state.encoder_pulse[1]++;		
    }
    exti_interrupt_flag_clear(EXTI_1);
}

void EXTI2_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_2)){
	        move_state.encoder_pulse[2]++;		
    }
    exti_interrupt_flag_clear(EXTI_2);
}

void EXTI3_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_3)){
	        move_state.encoder_pulse[3]++;		
    }
    exti_interrupt_flag_clear(EXTI_3);
}

Code snippet #10

Plain text
void movement_system_init(void)
{
	  rcu_periph_clock_enable(RCU_SYSCFG);
	
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
	  nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN0);
	  exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_0);
	
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
	  nvic_irq_enable(EXTI1_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN1);
	  exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_1);

	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
	  nvic_irq_enable(EXTI2_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN2);
	  exti_init(EXTI_2, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_2);
		
	  gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
	  nvic_irq_enable(EXTI3_IRQn, 2U, 0U);
      syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN3);
	  exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_RISING);
      exti_interrupt_flag_clear(EXTI_3);
}
	
void EXTI0_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_0)){
	        move_state.encoder_pulse[0]++;		
    }
    exti_interrupt_flag_clear(EXTI_0);
}

void EXTI1_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_1)){
	        move_state.encoder_pulse[1]++;		
    }
    exti_interrupt_flag_clear(EXTI_1);
}

void EXTI2_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_2)){
	        move_state.encoder_pulse[2]++;		
    }
    exti_interrupt_flag_clear(EXTI_2);
}

void EXTI3_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_3)){
	        move_state.encoder_pulse[3]++;		
    }
    exti_interrupt_flag_clear(EXTI_3);
}

Github

https://github.com/tuya/tuya-iotos-embeded-mcu-demo-wifi-ble-samrt-lawn-mower

Credits

Sandwich IoT
40 projects • 5 followers

Comments