[英]How can i controll two servo motor and buzzer with arduino mega2560 without using any library function
我尝试了以下代码……我已经成功运行了 1 个伺服和 1 个蜂鸣器,但我无法同时运行 2 个伺服……我的代码没有正常工作……我的伺服引脚是 11 & 12……我的蜂鸣器引脚是 5……这是我的代码和电路图……我图中的 uno 是一个巨型,只是为了确定……同样,我不能使用任何库函数像 pinMode() 或任何用于控制蜂鸣器或伺服的库....所以这是我的图表和代码
#define servo90 3000 //OCR1A value for the servo to reach 90 degrees
#define servo0 1000 //OCR1A value for the servo to reach 0 degrees
#define servoA90 3000 //OCR1A value for the servo to reach 90 degrees
#define servoA0 1000
volatile unsigned long sysTick = 0; //set up a global system tick variable
unsigned long oldSysTickServo = 0;
volatile unsigned long sysTickA = 0; //set up a global system tick variable
unsigned long oldSysTickServoA = 0;
//Buzzer I/O signal is connected to PIN 5
int tune1[] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440};
int dur1[] = {500, 500, 500, 500, 500, 500, 500, 500, 50};
int i, j, n = 10; //n is inialitsed to the number o fnotes in tune 1.
int tmp;
void setup() {
DDRB = (1 << DDB5); //Set PB 5 (pin 11) to an output
DDRB = (1 << DDB6);
//set up a 1ms system tick timer
cli(); //disable global interrupts
TCCR0A = 0;
TCCR0B = (1 << CS01) | (1 << CS00); //start the timer with a prescale of 64
TIMSK0 = (1 << OCIE0A); //setup the output compare interrupt with OCR0A
OCR0A = 250; //set up the OCR0A value for exactly 1ms (or as close as the clock will allow)
sei(); //enable global interrupts
//setup the timer for fast PWM
TCCR1A = (1 << COM1A1) | (1 << WGM11); //Enable clear on OC1A
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); //Set the prescale to 8 bits, Fast PWM with TOP in ICR1
TCCR1C = 0; //We dont need to do anything here, so make sure its shut off
ICR1 = 40000; //Set the top value to 40000. This should be a period of 20ms
OCR1A = servo90;
// setup the timer for 2nd pwm
TCCR1A = (1 << COM1B1) | (1 << WGM11); //Enable clear on OC1B
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); //Set the prescale to 8 bits, Fast PWM with TOP in ICR1
TCCR1C = 0; //We dont need to do anything here, so make sure its shut off
ICR1 = 40000; //Set the top value to 40000. This should be a period of 20ms
OCR1B = servoA90;
// bazar timer count
DDRE = (1 << DDE3);
TCCR3A = (1 << COM3A1) | (1 << WGM31);
TCCR3B = (1 << WGM33) | (1 << WGM32) | (1 << CS32);
}
void loop() {
for (i = 0; i < n; i++) {
ICR3 = tune1[i];
OCR3A = tune1[i] / 2;
TCNT3 = 0;
for (j = 0; j < dur1[i]; j++) {
_delay_ms(1);
}
ICR3 = 0; OCR3A = 0; TCNT3 = 0;
//Has half a second passed?
if (sysTickVal() >= oldSysTickServo + 500)
{
oldSysTickServo = sysTickVal(); //store the previous time
//is the servo currently down?
if (OCR1A == servo0)
{
//the servo is currently at 0 deg
OCR1A = servo90; //set the servo to 90deg
}
else
{
//the servo is currently at 90 deg
OCR1A = servo0; //set the servo to 90deg
}
}
//Has half a second passed?
if (sysTickValA() >= oldSysTickServoA + 500)
{
oldSysTickServoA = sysTickValA(); //store the previous time
//is the servo currently down?
if (OCR1B == servoA0)
{
//the servo is currently at 0 deg
OCR1B = servoA90; //set the servo to 90deg
}
else
{
//the servo is currently at 90 deg
OCR1B = servoA0; //set the servo to 90deg
}
}
}
}
ISR(TIMER0_COMPA_vect)
{
sysTickA++;
sysTick++;
//increment the system tick time every 1ms
TCNT0 = 0; //reset the timer
}
/**************************************************************************************************************************************/
//Function Name: get sysTick
//Inputs:
//Outputs:
//Hardware:
//Description: return the sytick value without any collitions
unsigned long sysTickValA()
{
unsigned long val; //create a variable to store the sysTick value
cli(); //disable gloabl interrupt
val = sysTickA; //read in the current system time
sei(); //enable global interrupt
return val; //return the current system time
}
unsigned long sysTickVal()
{
unsigned long val; //create a variable to store the sysTick value
cli(); //disable gloabl interrupt
val = sysTick; //read in the current system time
sei(); //enable global interrupt
return val; //return the current system time
}
不要对 DDRB 进行两次分配,只保留最后一个激活,而是使用两个位都设置的单个分配,例如:
DDRB = (1<<DDB5) | (1<<DDB6)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.