Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Timer 使用伺服和软件串行时出现计时器冲突问题_Timer_Arduino_Collision_Servo_Software Serial - Fatal编程技术网

Timer 使用伺服和软件串行时出现计时器冲突问题

Timer 使用伺服和软件串行时出现计时器冲突问题,timer,arduino,collision,servo,software-serial,Timer,Arduino,Collision,Servo,Software Serial,我在Arduino纳米板上使用Servo.h和SoftwareSerial.h时遇到计时器冲突问题。现在我需要2对串行引脚,通过在我的笔记本电脑上使用NFC模块和Arduino的串行监视器 如果我得到的信息没有错的话,nanoboard中有三个定时器(timer0、timer1、timer2)。我听说timer1是16位计时器,Servo.h和SoftwareSerial.h在Nano板上同时使用该计时器,这就是为什么他们无法避免计时器冲突问题 但是我需要使用两个头文件,而不需要计时器冲突。在这

我在Arduino纳米板上使用Servo.h和SoftwareSerial.h时遇到计时器冲突问题。现在我需要2对串行引脚,通过在我的笔记本电脑上使用NFC模块和Arduino的串行监视器

如果我得到的信息没有错的话,nanoboard中有三个定时器(timer0、timer1、timer2)。我听说timer1是16位计时器,Servo.h和SoftwareSerial.h在Nano板上同时使用该计时器,这就是为什么他们无法避免计时器冲突问题

但是我需要使用两个头文件,而不需要计时器冲突。在这种情况下,我应该怎么做?我是否必须修改Servo.h文件以不使用timer1

因为我用伺服电机所做的就是控制角度位置

因此,除非我使用PWM控制,否则使用16位定时器在本项目中没有任何用处

所以,在这一点上,我想使用timer0或timer2(都是8位计时器)而不是timer1。否则,伺服头文件和软件头文件中的计时器1将发生冲突。 下面是我使用的源代码

const unsigned char wake[24]={
  0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
  0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
  0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_ACK[25] = {
  0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, 
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
unsigned char old_id[5];

unsigned char receive_ACK[25];//Command receiving buffer
//int inByte = 0;               //incoming serial byte buffer

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define print1Byte(args) mySerial.write(args)
#define print1lnByte(args)  mySerial.write(args),mySerial.println()
#else
#include "WProgram.h"
#define print1Byte(args) mySerial.print(args,BYTE)
#define print1lnByte(args)  mySerial.println(args,BYTE)
#endif

#include <Servo.h>
#include <NeoSWSerial.h>

NeoSWSerial mySerial(5,6);

volatile uint32_t newlines = 0UL;

Servo sv;

int pos1=0; //initial value = 93 degree
int pos2=180;
int sw1 = 4;

static void handleRxChar( uint8_t c )
    {
      if (c == '\n')
        newlines++;
    }

void setup(){
  mySerial.attachInterrupt( handleRxChar );
  pinMode(sw1, INPUT_PULLUP);
  sv.attach(9);
  Serial.begin(9600);  // open serial with PC
  mySerial.begin(9600);  //open serial1 with device
  //Serial2.begin(115200);
  wake_card();
  delay(100);
  read_ACK(15);
  delay(100);
  display(15);
}

void loop(){
  send_tag(); 
  read_ACK(25);
  delay(100);
  if (!cmp_id ()) {   //nfc tag
    if (test_ACK ()) {
      display (25);
      sv.write(pos1);
      delay(2500);
      sv.write(pos2);
    }
  }
  else if (cmp_id()){   // switch
    if(digitalRead(sw1) == LOW){
      sv.write(pos1);   // waits 15ms for the servo to reach the position
      }
    else if(digitalRead(sw1) == HIGH){
      sv.write(pos2);
    }
  }
  copy_id ();
}

void copy_id (void) {//save old id
  int ai, oi;
  for (oi=0, ai=19; oi<5; oi++,ai++) {
    old_id[oi] = receive_ACK[ai];
  }
}

char cmp_id (void){//return true if find id is old
  int ai, oi;
  for (oi=0,ai=19; oi<5; oi++,ai++) {
    if (old_id[oi] != receive_ACK[ai])
      return 0;
  }
  return 1;
}

int test_ACK (void) {// return true if receive_ACK accord with std_ACK
  int i;
  for (i=0; i<19; i++) {
    if (receive_ACK[i] != std_ACK[i])
      return 0;
  }
  return 1;
}

void send_id (void) {//send id to PC
  int i;
  Serial.print ("ID: ");
  for (i=19; i<= 23; i++) {
    Serial.print (receive_ACK[i], HEX);
    Serial.print (" ");
  }
  Serial.println ();
}

void UART1_Send_Byte(unsigned char command_data){//send byte to device
  print1Byte(command_data);
#if defined(ARDUINO) && ARDUINO >= 100
  mySerial.flush();// complete the transmission of outgoing serial data 
#endif
} 

void UART_Send_Byte(unsigned char command_data){//send byte to PC
  Serial.print(command_data,HEX);
  Serial.print(" ");
} 

void read_ACK(unsigned char temp){//read ACK into reveive_ACK[]
  unsigned char i;
  for(i=0;i<temp;i++) {
    receive_ACK[i]= mySerial.read();
  }
}

void wake_card(void){//send wake[] to device
  unsigned char i;
  for(i=0;i<24;i++) //send command
    UART1_Send_Byte(wake[i]);
}

void firmware_version(void){//send fireware[] to device
  unsigned char i;
  for(i=0;i<9;i++) //send command
    UART1_Send_Byte(firmware[i]);
}

void send_tag(void){//send tag[] to device
  unsigned char i;
  for(i=0;i<11;i++) //send command
    UART1_Send_Byte(tag[i]);
}

void display(unsigned char tem){//send receive_ACK[] to PC
  unsigned char i;
  for(i=0;i<tem;i++) //send command
    UART_Send_Byte(receive_ACK[i]);
  Serial.println();
}
const无符号字符唤醒[24]={
0x55,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00、0x00、0x00、0x00、0x00、0x00、0xff、0x03、0xfd、0xd4、0x14、0x01、0x17、0x00}//唤醒NFC模块
常量无符号字符固件[9]={
0x00,0x00,0xFF,0x02,0xFE,0xD4,0x02,0x2A,0x00}//
常量无符号字符标记[11]={
0x00,0x00,0xFF,0x04,0xFC,0xD4,0x4A,0x01,0x00,0xE1,0x00}//检测标记命令
常量无符号字符标准确认[25]={
0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x0C,
0xF4、0xD5、0x4B、0x01、0x01、0x00、0x04、0x08、0x04、0x00、0x00、0x00、0x00、0x4B、0x00};
无符号字符old_id[5];
未签名字符接收确认[25]//命令接收缓冲器
//int-inByte=0//传入串行字节缓冲区
#如果定义(ARDUINO)&&ARDUINO>=100
#包括“Arduino.h”
#定义print1Byte(args)mySerial.write(args)
#定义print1lnByte(args)mySerial.write(args),mySerial.println()
#否则
#包括“WProgram.h”
#定义print1Byte(args)mySerial.print(args,BYTE)
#定义print1lnByte(args)mySerial.println(args,BYTE)
#恩迪夫
#包括
#包括
新系列糠秕(5,6);
易失性uint32_t换行符=0UL;
伺服sv;
int pos1=0//初始值=93度
int pos2=180;
int sw1=4;
静态空心手柄XCHAR(uint8\U t c)
{
如果(c=='\n')
换行符++;
}
无效设置(){
mySerial.attachInterrupt(handleRxChar);
pinMode(sw1,输入\上拉);
sv.附件(9);
Serial.begin(9600);//用PC打开串口
mySerial.begin(9600);//使用设备打开serial1
//序列2.开始(115200);
唤醒卡();
延迟(100);
阅读确认(15);
延迟(100);
显示器(15);
}
void循环(){
发送标签();
阅读确认(25);
延迟(100);
如果(!cmp_id()){//nfc标记
如果(测试确认()){
显示器(25);
sv.write(pos1);
延迟(2500);
sv.write(pos2);
}
}
else if(cmp_id()){//开关
如果(数字读取(sw1)=低){
sv.write(pos1);//等待15毫秒,等待伺服到达该位置
}
否则如果(数字读取(sw1)=高){
sv.write(pos2);
}
}
拷贝id();
}
作废副本\u id(作废){//保存旧id
国际ai,oi;

对于(oi=0,ai=19;oi正常情况下,我会建议将
AltSoftSerial
作为
SoftwareSerial
的替代品(请阅读更多),但它也与伺服库的TIMER1使用相冲突。它只能在两个特定引脚上使用

我想我的电脑可以做到这一点。它重新使用
micros()
时钟(TIMER0)和插脚更改中断来实现软件串行端口。这将它限制为波特率9600、19200和38400,但它比
SoftwareSerial
高效得多。它可以在任何两个插脚上使用。

更新 我不建议在115200使用软件串行端口,因为它在38400以上可能不可靠。您可以向NFC模块发送波特率配置命令,将其设置为较低的速率

顺便说一句,如果您正在发送信息(不仅仅是接收),则所有软件串行端口库都会在传输过程中禁用中断,除了不能使用的
AltSoftSerial
。请注意这一点,因为在
NeosWSSerial
上传输时,它可能会影响伺服

此外,请确保您正在为伺服使用一个PWM引脚。如果伺服库正在使用软件(就像软件串行端口一样)创建PWM信号,CPU将没有时间进行其他工作

最好将NFC模块放在硬件串行端口上,
serial
。对于调试打印,请使用连接到TTL串行到USB转换器的
NeoSWSerial
。然后打开该转换器COM端口上的串行监视器。稍后删除调试,因为传输会禁用中断


还有其他具有额外UART的板。例如,Arduino Leo(ATMega32U4 MCU)有一个额外的串行端口,
Serial1
,可用于NFC。
serial
仍可用于调试打印。

通常,我会建议使用
AltSoftSerial
作为
SoftwareSerial
的替代品(阅读更多),但它也与伺服库的TIMER1使用冲突。它只能用于两个特定的引脚

我想我的电脑可以做到这一点。它重新使用
micros()
时钟(TIMER0)和插脚更改中断来实现软件串行端口。这将它限制为波特率9600、19200和38400,但它比
SoftwareSerial
高效得多。它可以在任何两个插脚上使用。

更新 我不建议在115200使用软件串行端口,因为它在38400以上可能不可靠。您可以向NFC模块发送波特率配置命令,将其设置为较低的速率

顺便说一句,如果您正在发送信息(不仅仅是接收),则所有软件串行端口库都会在传输过程中禁用中断