欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

树莓派和步进电机的故事

程序员文章站 2022-07-12 19:28:32
...

程序员从来不缺少对新事物的好奇心和动手探索未知世界的勇气。

从听说树莓派到因好奇购买Model B已经有两年多,最近重新找出来是想实现一台简易的电火花机(电极控制模块),做电火花机是为了给高速钢打孔。

 

电火花机长什么样在网上可以找得到,就是取断丝锥用的型号;

电极控制模块设计思路大致如下:

 

初始时步进电机顺时针转动,电极逐渐靠近工件,达到临界值后开始放电产生电火花;此时工件和电极之间电流很小;

 

当电极和工件之间距离为零时,发生短路,此时电流会达到一个设定的极限值,传感器检测到之后将信号反馈给树莓派,然后控制步进电机逆时针转动,电极远离工件。

 

当电流小于某一临界值后,步进电机正转,如此往复......

 

步进电机和驱动版从网上购买,进电机控制代码如下,用C++编写,前期为了测试,加入了按键控制电机转动方向的逻辑。

 

#include "wiringPi.h"
#include <stdio.h>
#include <stdlib.h>

#include <signal.h>
#include <sys/time.h>

#include <time.h>

#define CLOCKWISE 1
#define COUNTER_CLOCKWISE 2

int flag = 1;

int btn_direction = 1;

int direction = 1;
int pin[] = {26, 27, 28, 29};

void rotate(int* pins, int direction);
void btnInterrupt();
int start_timer();
int main()
{
	if(wiringPiSetup() != -1)  //初始化wiringPi库
	{
		for(int pi = 0;pi < 4; pi++){
			pinMode(pin[pi], OUTPUT);
		}
		printf("test interrput\n");  //打印提示信息
		pinMode(btn_direction, INPUT); //引脚0为输入模式
		pullUpDnControl(btn_direction, PUD_UP);  //设置0号引脚上拉
	}else{
		printf("can't init wiringPi\n");  //初始化失败时,打印出提示信息,并且推出
		return -1;
	}


	//注册中断程序
	if(wiringPiISR(btn_direction, INT_EDGE_FALLING, &btnInterrupt) < 0)  //设置引脚下降沿触发
	{
		printf("unable ISR\n");
	}
        start_timer();
	while(1){
		if(direction == 1){
			rotate(pin, CLOCKWISE);
		}else{
			rotate(pin, COUNTER_CLOCKWISE);
		}
	}
	return 0;
}
//按键服务函数
void btnInterrupt()
{
	flag = 0;
}

void rotate(int* pins, int direction) {
	for (int i = 0; i < 4; i++) {
		if (CLOCKWISE == direction) {
			for (int j = 0; j < 4; j++) {
				if (j == i) {
					digitalWrite(pins[3 - j], 1); // output a high level 
				} else {
					digitalWrite(pins[3 - j], 0); // output a low level 
				}
			}
		} else if (COUNTER_CLOCKWISE == direction) {
			for (int j = 0; j < 4; j++) {
				if (j == i) {
					digitalWrite(pins[j], 1); // output a high level 
				} else {
					digitalWrite(pins[j], 0); // output a low level 
				}
			}
		}
		delay(2);
	}
}

void signalHandler(int signo)
{
    switch (signo){
        case SIGALRM:
            
            int kk = digitalRead(btn_direction);
            if(kk == 1 && flag == 0){
                if(direction == 1){//值被修改并且按键已经抬起
                    direction = 2;
                }else{
                    direction = 1;
                }
                flag = 1;
            }
            printf("%d\n", kk);
            break;
   }
}
//定时轮训变量状态,以确认步进电机方向
int start_timer()
{
    signal(SIGALRM, signalHandler);

    struct itimerval new_value, old_value;
    new_value.it_value.tv_sec = 0;
    new_value.it_value.tv_usec = 1;
    new_value.it_interval.tv_sec = 0;
    new_value.it_interval.tv_usec = 100000;
    setitimer(ITIMER_REAL, &new_value, &old_value);

    return 0;
}

 以上有一部分是为了测试时,物理按键消除抖动的,实际打孔时信号由电流传感器产生,不存在抖动问题。