学习笔记3 Linux定时器和sg90舵机的综合应用

今天学习了Linux的定时器功能,并复刻了学习51单片机时玩的智能感应垃圾桶项目。总体感觉难度不大。

先捏软柿子,sg90舵机,应该是市面上能能买到的最便宜的舵机了吧(我瞎说的,如果不是可以发链接给我)。我手上的sg90有3根线,红、褐线分别是Vcc和GND,橙黄线输入PWM波。通过改变PWM波的占空比可以改变sg90舵机的旋转角度。

sg90舵机 

输入的PWM波频率为50Hz,一个周期即为20ms。当占空比为1 : 40时,舵机角度转向0°(初始角度或参考角度),占空比为1 :20时,舵机转角为45°,为3:40转90°,为1:10转135°,为1:8时转180°。

所以这里就需要定出一个20ms的总时长,每次计数0.5ms的定时器来输出PWM波。

接下来就说一说Linux下的定时器功能。

定时器功能,是通过itimerval结构体以及函数setitimer产生的信号,系统随之使用signal信号处理
函数来处理产生的定时信号而实现的。

struct itimerval
 {
    /* Value to put into `it_value' when the timer expires. */
    struct timeval it_interval;
    /* Time to the next timer expiration. */
    struct timeval it_value;
 };
    /*it_interval:定时器的单次计数时间间隔*/
    /*it_value:定时器的启动时间*/
struct timeval
{
  __time_t tv_sec; /* Seconds. */
  __suseconds_t tv_usec; /* Microseconds. */
};
int setitimer (__itimer_which_t __which,
      const struct itimerval *__restrict __new,
      struct itimerval *__restrict __old)

setitimer()将value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。

函数形参的which有3种:

ITIMER_REAL //数值为0,计时器的值实时递减,发送的信号是SIGALRM。
ITIMER_VIRTUAL //数值为1,进程执行时递减计时器的值,发送的信号是SIGVTALRM。
ITIMER_PROF //数值为2,进程和系统执行时都递减计时器的值,发送的信号是SIGPROF。

我们这里使用第一种:

 signal(SIGALRM,signal_handler);

返回说明:
成功执行时,返回0。失败返回-1

signal_handler函数很像51,32单片机的中断处理函数,可以类比理解。
 

有了上面两个知识,稍微结合一下,就可以实现键盘输入数字,舵机对应旋转到指定角度了。

代码如下:

#include "stdio.h"
#include "sys/time.h"
#include "stdlib.h"
#include "signal.h"
#include "wiringPi.h"

#define SG90_PIN 5

int angle;

void signal_handler(int signum)
{
	static int i = 0;

	if(i <= angle)
	{
		digitalWrite(SG90_PIN, HIGH);
	}
	else
	{
		digitalWrite(SG90_PIN, LOW);
	}
	if(i == 40)
	{
		i = 0;
	}
	i++;	
}

int main(void)
{
	struct itimerval itv;

	wiringPiSetup();
	pinMode(SG90_PIN, OUTPUT);

	angle = 0;

	/*setting the interval*/
	itv.it_interval.tv_sec = 0;
	itv.it_interval.tv_usec = 500;
	/*setting the beginning time*/
	itv.it_value.tv_sec = 1;
	itv.it_value.tv_usec = 0;
	/*setting the timer_mode*/
	if(setitimer(ITIMER_REAL, &itv, NULL) == -1)
	{
		perror("error");
		exit(-1);
	}
	/*handle the signal*/
	signal(SIGALRM, signal_handler);
	while(1)
	{
		printf("please input the angle: 1(0), 2(45), 3(90), 4(135)");
		scanf("%d", &angle);
	}

	return 0;
}

对应现象就是键盘输入1时,舵机转向0度,2->45度,3->90度,4->135度,5->180度。

和上一篇日志内容相结合就可以实现感应垃圾的主体结构了

代码如下:

#include "stdio.h"
#include "sys/time.h"
#include "stdlib.h"
#include "signal.h"
#include "wiringPi.h"
#include "unistd.h"

#define Trig 0
#define Echo 1
#define SG90_PIN 5

int angle;

double getDistance(void)
{
	struct timeval start, stop;
	long diffTime;
	double dist;

	pinMode(Trig, OUTPUT);
	pinMode(Echo, INPUT);

	digitalWrite(Trig, LOW);
	usleep(5);
	digitalWrite(Trig, HIGH);
	usleep(10);
	digitalWrite(Trig, LOW);//HC-04 Trig signal
	
	while(!digitalRead(Echo));
	gettimeofday(&start, NULL);
	while(digitalRead(Echo));
	gettimeofday(&stop, NULL);
	diffTime = 1000000 *(stop.tv_sec - start.tv_sec) + (stop.tv_usec - start.tv_usec);
	printf("diffTime  = %ld\n", diffTime);
	dist = (double)diffTime/1000000*340/2*100;//(unit:cm) 
	return dist;
}

void signal_handler(int signum)
{
	static int i = 0;

	if(i <= angle)
	{
		digitalWrite(SG90_PIN, HIGH);
	}
	else
	{
		digitalWrite(SG90_PIN, LOW);
	}
	if(i == 40)
	{
		i = 0;
	}
	i++;	
}

void init_SG90()
{
	angle = 0;	//init angle
	pinMode(SG90_PIN, OUTPUT);
	/*setting the interval*/
	itv.it_interval.tv_sec = 0;
	itv.it_interval.tv_usec = 500;
	/*setting the beginning time*/
	itv.it_value.tv_sec = 1;
	itv.it_value.tv_usec = 0;
	/*setting the timer_mode*/
	if(setitimer(ITIMER_REAL, &itv, NULL) == -1)
	{
		perror("error");
		exit(-1);
	}
	/*handle the signal*/
	signal(SIGALRM, signal_handler);
}

int main(void)
{
	double distance;

	if(wiringPiSetup() == -1)
	{
		fprintf(stderr, "%s", "initWiringPi error");
		exit(-1);
	}
	init_SG90();

	while(1)
	{
		distance = getDistance();
		if(distance < 10)
		{
			angle = 5;
		}
		else
		{
			angle = 2;
		}	
        sleep(2);		
	}
	return 0;
}

现象就是当物体距离超声波传感器小于10cm时,舵机转动,大于10cm时恢复角度。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值