6884|11

862

帖子

2

TA的资源

纯净的硅(初级)

楼主
 

[GD32F350]第六弹:基于GD32和威纶触摸屏的多轴步进电机驱动控制器开发作品提交 [复制链接]

 
[GD32F350]第六弹:基于GD32和威纶触摸屏的多轴步进电机驱动控制器开发作品提交


一、本文背景
      本试用项目出自一不锈钢型材(管材)暖气片生产厂家内的一台暖气片自动焊机,见下图,底轴为公用轴,负责焊枪左右移动。轴上有前后两个平台,每个平台有一个可以前后移动的轴和一个可以旋转一定角度的轴组成,用来调整前后焊枪前后位置以及焊枪角度。驱动是5台步进电机,焊机焊接过程中,需要5个轴的电机能够按照一定关系联动。
      所以本次试用用GD32做为主控,来开发一台5“轴”步进电机联动的驱动装置。

      基于手中只有4台完整的步进电机及驱动装置,因此,文中看到的是驱动了4台电机之后的样子,另外一台没有接。
2、任务目标
本次要实现的一些任务:
    2.1作为一款国产的cortex内核的单片机,价格应该会有优势,但是稳定性和程序开发的难易程度如何,需要一些验证,这个主要是本次试用的一个主要目的。
    本次试用主要体验了一下GD32F350的外设有:GPIO、USART、DMA、定时器、systick以及一些中断,有些外设用到的功能相对简单,所以没有单独开贴。
    2.2软件部分用到的内容,软件主要试用了循环缓冲和计算机图形学里边用到的布雷森汉姆线性插值算法,一般是直线,但是可以任意扩展到多维的空间,具体的作用原理在CSDN有很多不错的贴子,在此不再班门弄斧,下边会讲一下简单的原理,而循环缓冲主要用来存储焊机在焊接过程中每一段五个电机的一些数据,比如:速度值、位移量/单次脉冲数、方向等信息,算法的执行部分在定时中断服务函数内完成。
3、功能框图

步进驱动隔离电路,传感器限位隔离电路见下图:

图:传感器输入隔离电路

图:输出隔离控制步进驱动电路
图中vin为24V直流。
4、流程示意图
主程序:

定时器中断服务函数:

USART空闲中断函数(数据处理在主函数中完成):

5、相关演示视频
布雷森汉姆算法测试

手动模式测试+循环缓冲区使用:

手动模式测试+硬件平台全景:

4台步进电机正反转手动模式测试:

6、部分代码如下:
定时中断部分:
  1. /* USER CODE BEGIN 1 */
  2. void TIM_PeriodElapsedCallback(uint32_t timer_periph)
  3. {
  4.     if(TIMER5 == timer_periph)
  5.     {
  6.         /********************       加载新block   *********************/
  7.         // If there is no current block, attempt to pop one from the buffer
  8.         if (current_exec_seg == NULL)
  9.         {
  10.             // Anything in the buffer?
  11.             current_exec_seg = plan_get_current_block();
  12.             if (current_exec_seg != NULL)
  13.             {
  14.                 /**************  count init    *************/
  15.                 current_exec_seg->busy = TRUE;  //执行期间 忙 标识
  16.                 count_x = -(current_exec_seg->step_event_count >> 1);
  17.                 count_y_a = count_x;
  18.                 count_y_b = count_x;
  19.                 count_r_a = count_x;
  20.                 count_r_b = count_x;
  21.                 step_completed = 0;
  22. #ifdef DEBUG_PRINTF
  23.                 printf("tim1_ISR:x:%ld,ya=%ld,yb=%ld,ra=%ld,rb=%ld\r\n", count_x, count_y_a, count_y_b, count_r_a, count_r_b);

  24. #endif
  25.                 /************** end count init    *************/
  26.                 /****************  方向预处理      **************/
  27.                 if(sys_state == SYS_MOVE_RIGHT) //x轴、ra、rb轴方向取反  计数方向取反
  28.                 {
  29.                     //方向预处理
  30.                     current_exec_seg->dir_x = !current_exec_seg->dir_x;
  31.                     current_exec_seg->dir_r_a = !current_exec_seg->dir_r_a;
  32.                     current_exec_seg->dir_r_b = !current_exec_seg->dir_r_b;
  33.                 }
  34.                 /****************  end 方向预处理      **************/

  35.                 // current_exec_seg_null = BUFFERNOTEMPTY;

  36.                 dirvertimerSetArr(current_exec_seg->feed_rate);
  37.             }
  38.             else  //没有更多的seg可执行了
  39.             {
  40.                 //  current_exec_seg_null = BUFFEREMPTY;
  41.                 dirvertimerSetArr(3000 - 1);
  42.             }
  43.         }
  44.         /********************   end    加载新block   *********************/

  45.         if (current_exec_seg != NULL)
  46.         {
  47.             /********************       设置输出方向引脚、计数方向   *********************/
  48.             // Set direction en check limit switches
  49.             /***************    X     ***************/
  50.             if ( current_exec_seg->dir_x != LEFT)   // RIGHT:stepping along -X axis
  51.             {
  52.               GPIO_BOP(GPIOC)=GPIO_PIN_0;
  53.                 count_direction[X_AXIS] = -1;
  54.                 CHECK_ENDSTOPS
  55.                 {
  56. #if defined X_MIN_PIN   //反方向行走,检测MIN限位
  57.                     uint8_t x_min_endstop = X_MIN_PIN != X_ENDSTOPS_INVERTING ;
  58.                     if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0))   //两次连续进来都检测到限位了,并且剩余脉冲数大于0,说明block没有执行完,但是到了限位
  59.                     {
  60.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];    //记录位置
  61.                         endstop_x_hit = TRUE;                                   //触发限位为真
  62.                         step_events_completed = current_block->step_event_count;//完成的步数等于当前累计值
  63.                     }
  64.                     old_x_min_endstop = x_min_endstop;
  65. #endif
  66.                 }
  67.             }
  68.             else   //1: +direction   正方向行走
  69.             {

  70.                 GPIO_BC(GPIOC)=GPIO_PIN_0;
  71.                 count_direction[X_AXIS] = 1;
  72.                 CHECK_ENDSTOPS
  73.                 {
  74. #if defined X_MAX_PIN
  75.                     uint8_t x_max_endstop = X_MAX_PIN != X_ENDSTOPS_INVERTING;
  76.                     if(x_max_endstop && old_x_max_endstop && (current_exec_seg->steps_x > 0))
  77.                     {
  78.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  79.                         endstop_x_hit = TRUE;
  80.                         step_events_completed = current_exec_seg->step_event_count;
  81.                     }
  82.                     old_x_max_endstop = x_max_endstop;
  83. #endif
  84.                 }
  85.             }
  86.             /***************   END X     ***************/

  87.             /***************    Y_A     ***************/
  88.             if ( current_exec_seg->dir_y_a != FORWARD_Y_A)   // BACKWARD:stepping along -Y axis
  89.             {
  90.                 GPIO_BOP(GPIOC)=GPIO_PIN_2;
  91.                 count_direction[Y_A_AXIS] = -1;
  92.                 CHECK_ENDSTOPS
  93.                 {
  94. #if defined Y_A_MIN_PIN   //反方向行走,检测MIN限位
  95.                     uint8_t y_a_min_endstop = Y_A_MIN_PIN != Y_A_ENDSTOPS_INVERTING ;
  96.                     if(y_a_min_endstop && old_y_a_min_endstop && (current_exec_seg->steps_y_a > 0))
  97.                     {
  98.                         //endstops_trigsteps[X_AXIS] = count_position[X_AXIS];    //记录位置  保留
  99.                         endstop_y_a_hit = TRUE;                                   //触发限位为真
  100.                         step_completed = current_exec_seg->step_event_count;//到达限位位置,直接将step_completed给到最大
  101.                     }
  102.                     old_y_a_min_endstop = y_a_min_endstop;
  103. #endif
  104.                 }
  105.             }
  106.             else   //1: +direction   正方向行走
  107.             {

  108.                 GPIO_BC(GPIOC)=GPIO_PIN_2;
  109.                 count_direction[Y_A_AXIS] = 1;
  110.                 CHECK_ENDSTOPS
  111.                 {
  112. #if defined Y_A_MAX_PIN  //保留 下边未修改
  113.                     uint8_t x_max_endstop = X_MAX_PIN != X_ENDSTOPS_INVERTING;
  114.                     if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0))
  115.                     {
  116.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  117.                         endstop_x_hit = TRUE;
  118.                         step_events_completed = current_block->step_event_count;
  119.                     }
  120.                     old_x_max_endstop = x_max_endstop;
  121. #endif
  122.                 }
  123.             }
  124.             /***************  END Y_A     ***************/
  125.             /***************    Y_B     ***************/
  126.             if ( current_exec_seg->dir_y_b != FORWARD_Y_B)   // BACKWARD:stepping along -Y axis
  127.             {
  128.                 GPIO_BOP(GPIOC)=GPIO_PIN_4;
  129.                 count_direction[Y_B_AXIS] = -1;
  130.                 CHECK_ENDSTOPS
  131.                 {
  132. #if defined Y_B_MIN_PIN   //反方向行走,检测MIN限位
  133.                     uint8_t y_b_min_endstop = Y_B_MIN_PIN != Y_B_ENDSTOPS_INVERTING ;
  134.                     if(y_b_min_endstop && old_y_b_min_endstop && (current_exec_seg->steps_y_b > 0))
  135.                     {
  136.                         //endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  137.                         endstop_y_b_hit = TRUE;
  138.                         step_completed = current_exec_seg->step_event_count;//到达限位位置,直接将step_completed给到最大
  139.                     }
  140.                     old_y_b_min_endstop = y_b_min_endstop;
  141. #endif
  142.                 }
  143.             }
  144.             else   //1: +direction   正方向行走
  145.             {

  146.                 GPIO_BC(GPIOC)=GPIO_PIN_4;
  147.                 count_direction[Y_B_AXIS] = 1;
  148.                 CHECK_ENDSTOPS
  149.                 {
  150. #if defined Y_B_MAX_PIN  //保留 下边未修改
  151.                     uint8_t x_max_endstop = X_MAX_PIN != X_ENDSTOPS_INVERTING;
  152.                     if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0))
  153.                     {
  154.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  155.                         endstop_x_hit = TRUE;
  156.                         step_events_completed = current_block->step_event_count;
  157.                     }
  158.                     old_x_max_endstop = x_max_endstop;
  159. #endif
  160.                 }
  161.             }
  162.             /***************  END  Y_B     ***************/
  163.             /*****************    R_A     ***************/
  164.             if ( current_exec_seg->dir_r_a != CW_R_A)   // CCW:stepping along -RA axis
  165.             {
  166.                 GPIO_BOP(GPIOC)=GPIO_PIN_6;
  167.                 count_direction[R_A_AXIS] = -1;
  168.                 CHECK_ENDSTOPS
  169.                 {
  170. #if defined R_A_MIN_PIN   //反方向行走,检测MIN限位
  171.                     uint8_t r_a_min_endstop = R_A_MIN_PIN != y_A_ENDSTOPS_INVERTING ;
  172.                     if(r_a_min_endstop && old_r_a_min_endstop && (current_exec_seg->steps_r_a > 0))
  173.                     {
  174.                         //endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  175.                         endstop_r_a_hit = TRUE;
  176.                         step_completed = current_exec_seg->step_event_count;
  177.                     }
  178.                     old_r_a_min_endstop = r_a_min_endstop;
  179. #endif
  180.                 }
  181.             }
  182.             else   //1: +direction   正方向行走
  183.             {

  184.                 GPIO_BC(GPIOC)=GPIO_PIN_6;
  185.                 count_direction[R_A_AXIS] = 1;
  186.                 CHECK_ENDSTOPS
  187.                 {
  188. #if defined R_A_MAX_PIN  //保留 下边未修改
  189.                     uint8_t x_max_endstop = X_MAX_PIN != X_ENDSTOPS_INVERTING;
  190.                     if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0))
  191.                     {
  192.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  193.                         endstop_x_hit = TRUE;
  194.                         step_events_completed = current_block->step_event_count;
  195.                     }
  196.                     old_x_max_endstop = x_max_endstop;
  197. #endif
  198.                 }
  199.             }
  200.             /***************  END R_A   ***************/
  201.             /***************    R_B     ***************/
  202.             if ( current_exec_seg->dir_r_b != CW_R_B)   // CCW:stepping along -RB axis
  203.             {
  204.                 GPIO_BOP(GPIOC)=GPIO_PIN_8;
  205.                 count_direction[R_B_AXIS] = -1;
  206.                 CHECK_ENDSTOPS
  207.                 {
  208. #if defined R_B_MIN_PIN   //反方向行走,检测MIN限位
  209.                     uint8_t r_b_min_endstop = R_B_MIN_PIN != y_B_ENDSTOPS_INVERTING ;
  210.                     if(r_b_min_endstop && old_r_b_min_endstop && (current_exec_seg->steps_r_b > 0))
  211.                     {
  212.                         //endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  213.                         endstop_r_b_hit = TRUE;
  214.                         step_completed = current_exec_seg->step_event_count;
  215.                     }
  216.                     old_r_b_min_endstop = r_b_min_endstop;
  217. #endif
  218.                 }
  219.             }
  220.             else   //1: +direction   正方向行走
  221.             {

  222.                 GPIO_BC(GPIOC)=GPIO_PIN_8;
  223.                 count_direction[R_B_AXIS] = 1;
  224.                 CHECK_ENDSTOPS
  225.                 {
  226. #if defined R_B_MAX_PIN  //保留 下边未修改
  227.                     uint8_t x_max_endstop = X_MAX_PIN != X_ENDSTOPS_INVERTING;
  228.                     if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0))
  229.                     {
  230.                         endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
  231.                         endstop_x_hit = TRUE;
  232.                         step_events_completed = current_block->step_event_count;
  233.                     }
  234.                     old_x_max_endstop = x_max_endstop;
  235. #endif
  236.                 }
  237.             }
  238.             /***************   END R_B     ***************/

  239.             /********************     end  设置输出方向引脚、计数方向   *********************/
  240.             /***********************  JG  ***************************/
  241.             if(waitJG)//只有在等待激光的过程中,waitJG才有效,其他阶段不执行内部内容。
  242.             {
  243.                 JG_JianCe_Flag = JG_PIN != JG_JIANCE_INVERTING;
  244.                 if(JG_JianCe_Flag && JG_JianCe_Old_Flag && (current_exec_seg->steps_x > 0))
  245.                 {
  246.                     JianCeDanZhuOK = 1;
  247.                     step_completed = current_exec_seg->step_event_count;//本次seg强制执行完毕
  248.                 }
  249.                 JG_JianCe_Old_Flag = JG_JianCe_Flag;
  250.             }
  251.             /*********************** END JG  ***************************/

  252.             /********************       bresenham   *********************/
  253.             count_x += current_exec_seg->steps_x;
  254.             if (count_x > 0)
  255.             {
  256.                 GPIO_BC(GPIOC)=GPIO_PIN_1;
  257.                 //HAL_GPIO_WritePin  (M1_PULSE_GPIO_Port , M1_PULSE_Pin, GPIO_PIN_RESET );
  258.                 delay_us(15);
  259.                 count_x -= current_exec_seg->step_event_count;
  260.                 count_position[X_AXIS] += count_direction[X_AXIS];
  261.                 //                HAL_GPIO_WritePin  (M1_PULSE_GPIO_Port , M1_PULSE_Pin, GPIO_PIN_SET );
  262.                  GPIO_BOP(GPIOC)=GPIO_PIN_1;
  263.             }

  264.             count_y_a += current_exec_seg->steps_y_a;
  265.             if (count_y_a > 0)
  266.             {
  267.                 GPIO_BC(GPIOC)=GPIO_PIN_3;
  268.                 delay_us(15);
  269.                 count_y_a -= current_exec_seg->step_event_count;
  270.                 count_position[Y_A_AXIS] += count_direction[Y_A_AXIS];
  271.                 GPIO_BOP(GPIOC)=GPIO_PIN_3;
  272.             }

  273.             count_y_b += current_exec_seg->steps_y_b;
  274.             if (count_y_b > 0)
  275.             {
  276.                 GPIO_BC(GPIOC)=GPIO_PIN_5;
  277.                 delay_us(20);
  278.                 count_y_b -= current_exec_seg->step_event_count;
  279.                 count_position[Y_B_AXIS] += count_direction[Y_B_AXIS];
  280.                 GPIO_BOP(GPIOC)=GPIO_PIN_5;
  281.             }

  282.             count_r_a += current_exec_seg->steps_r_a;
  283.             if (count_r_a > 0)
  284.             {
  285.                 GPIO_BOP(GPIOC)=GPIO_PIN_7;
  286.                 delay_us(20);
  287.                 count_r_a -= current_exec_seg->step_event_count;
  288.                 count_position[R_A_AXIS] += count_direction[R_A_AXIS];
  289.                 GPIO_BC(GPIOC)=GPIO_PIN_7;
  290.             }

  291.             count_r_b += current_exec_seg->steps_r_b;
  292.             if (count_r_b > 0)
  293.             {
  294.                 GPIO_BOP(GPIOC)=GPIO_PIN_9;
  295.                 delay_us(20);
  296.                 count_r_b -= current_exec_seg->step_event_count;
  297.                 count_position[R_B_AXIS] += count_direction[R_B_AXIS];
  298.                 GPIO_BC(GPIOC)=GPIO_PIN_9;
  299.             }

  300.             step_completed += 1;

  301.             // If current block is finished, reset pointer
  302.             if (step_completed >= current_exec_seg->step_event_count)
  303.             {
  304.                 step_completed = 0;
  305.                 current_exec_seg = NULL;
  306.                 plan_discard_current_block(); //更新尾巴
  307.             }
  308.             /********************    end   bresenham   *********************/
  309.         }
  310.     }//END TIM5 INT CALLBACK

  311. }//END TIM INT CALLBACK
复制代码

7、暂时就这么多了,深夜更贴不易,人到中年,体会更加深刻,奈何白天工作忙,有补充的话,会在楼下更新。
由于不是集中开发,多是抽时间断断续续进行测试,程序很粗糙,欢迎各位志同道合的朋友多提宝贵意见。
此帖出自GD32 MCU论坛

最新回复

正好也想着通过dma和空闲中断实现串口数据的收发处理,代码虽然没了,思路还很清晰   详情 回复 发表于 2023-8-24 20:28
点赞 关注(2)
个人签名水不撩不知深浅 人不拼怎知输赢
 

回复
举报

5260

帖子

239

TA的资源

管理员

来自 2楼
 


附给评委补充材料:
wo4fisher
[GD32F350]第一弹:板已到位,开始点灯
wo4fisher
[GD32F350]第二弹:USART相关
wo4fisher
[GD32F350]第三弹:USART使用DMA+IDLE中断方式不定长字节数据收发
wo4fisher
[GD32F350]第四弹:modbusRTU协议实现
wo4fisher
[GD32F350]第五弹:f350连接威伦触摸屏实现真机通信


此帖出自GD32 MCU论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

862

帖子

2

TA的资源

纯净的硅(初级)

板凳
 
补充一:引脚分配
此帖出自GD32 MCU论坛
 
个人签名水不撩不知深浅 人不拼怎知输赢
 
 

回复

862

帖子

2

TA的资源

纯净的硅(初级)

4
 
nmg 发表于 2018-10-25 09:06
附给评委补充材料:

应nmg管理要求,补充一下工程代码
链接已隐藏,如需查看请登录或者注册

代码放网盘了,论坛上传太慢,文件不大,2.8M,7天有效。
此帖出自GD32 MCU论坛
 
个人签名水不撩不知深浅 人不拼怎知输赢
 
 

回复

862

帖子

2

TA的资源

纯净的硅(初级)

5
 
nmg 发表于 2018-10-25 09:06
附给评委补充材料:

已追加工程代码。压缩包论坛上传好久没成功,发了网盘链接。
此帖出自GD32 MCU论坛
 
个人签名水不撩不知深浅 人不拼怎知输赢
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

6
 

你好,代码可否发一份给我邮箱:361953672@qq.com

此帖出自GD32 MCU论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

7
 

您好,网盘中链接已经失效,能否发一下工程源码,感谢~!805808377@qq.com

此帖出自GD32 MCU论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

8
 

楼主您好,同求代码,感激不尽!267356468@qq.com

此帖出自GD32 MCU论坛

点评

不好意思,之前代码找不到了  详情 回复 发表于 2020-4-22 18:26
代码找不到了,不好意思,有什么问题,留言吧  详情 回复 发表于 2020-4-22 18:25
 
 
 

回复

862

帖子

2

TA的资源

纯净的硅(初级)

9
 
xiaorealer 发表于 2020-4-14 14:14 楼主您好,同求代码,感激不尽!267356468@qq.com

代码找不到了,不好意思,有什么问题,留言吧

此帖出自GD32 MCU论坛
 
个人签名水不撩不知深浅 人不拼怎知输赢
 
 

回复

862

帖子

2

TA的资源

纯净的硅(初级)

10
 
xiaorealer 发表于 2020-4-14 14:14 楼主您好,同求代码,感激不尽!267356468@qq.com

不好意思,之前代码找不到了

此帖出自GD32 MCU论坛
 
个人签名水不撩不知深浅 人不拼怎知输赢
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

11
 

找不着啊 。。。。。埋没了

此帖出自GD32 MCU论坛
 
 
 

回复

16

帖子

0

TA的资源

一粒金砂(中级)

12
 

正好也想着通过dma和空闲中断实现串口数据的收发处理,代码虽然没了,思路还很清晰

此帖出自GD32 MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表