【问题标题】:Serial.write causing void loop program to stop (Digital Pins stop responding)Serial.write 导致无效循环程序停止(数字引脚停止响应)
【发布时间】:2018-11-26 15:16:34
【问题描述】:

我在尝试通过 HC05 蓝牙模块通过 tx 和 rx 向另一个 arduino 发送一些串行数据时遇到问题。

整个项目正在开发一款混合动力卡丁车,并将 arduino 用作简单的 ECU 单元,通过 PID 速度控制控制直流电机的 PWM 输出。我一直在逐步开展该项目,并且已经使用 arduino 设置脚踏板并直接控制电子速度控制器(ESC)。我为此添加了一个简单的 PID 功能以及一个简单的霍尔传感器来检测速度,并且确实需要调整,但到目前为止效果很好。现在,当我尝试通过串行端口发送数据时,问题就来了。

我已经将蓝牙模块连接到单独的 arduino 上,并成功地将数据从一个带有电位器输入的 arduino 发送到另一个带有 3.5 英寸 TFT 屏幕的 arduino。当我尝试将项目的主端集成到 PID 控制的直流电机时,系统会冻结。从那以后,我移除了 PID 控制并返回直接控制,但它仍然失败,我尝试注释掉编码器的中断序列并为 RPM 设置一个静态值,但仍然冻结。如果我不尝试使用任何数字输出,则发送序列有效。我真的很困惑。可以在下面找到我尝试调试的代码。这不是完整的代码,已被分割成碎片以尝试消除此故障。但是在下面的这段代码中,如果我注释掉 sendData 函数,系统就会工作,并且电机会以相对于踏板输入的速度旋转。一旦我尝试发送数据,系统就会运行几秒钟然后冻结。数据仍在发送中,静态读数仅显示数字输出开始工作。

#include <TimerOne.h>
int previous = 0;
int Tavg = 0;                // the average
int Tout = 0;
int throttle = A0;
const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int ESCPin = 5;  
unsigned int counter=0;
int RPM;
long Time = 0;
long ReadInt = 0;

void docount()  // counts from the speed sensor
{
  counter++;  // increase +1 the counter value
} 

void timerIsr()
{
  Timer1.detachInterrupt();  //stop the timer
  Serial.print("Motor Speed: "); 
  RPM = (counter*75 );  // RPM= counterx10*60/8 (x10 for second, 8 counts in encoder, 60 minutes === 75x counter)
  Serial.print(RPM);  
  Serial.println(" Rotation per min"); Serial.print(Tout);Serial.print("= "); Serial.print(Tout*0.01961);Serial.println("V");
  counter=0;  //  reset counter to zero
  Timer1.attachInterrupt( timerIsr );  //enable the timer
}

void ReadEnc (){
  Timer1.initialize(100000); // set timer for 0.1sec
  attachInterrupt(0, docount, RISING);  // increase counter when speed sensor pin goes High
  Timer1.attachInterrupt( timerIsr ); // enable the timer
}
void sendData(){
  if (Serial.available()>0) {
    if (Serial.read() == 0){
      //Serial.println(sendChars);
      int RPMout = RPM;
      Serial.write("<");
      //delay(2);
      //Serial.write(sendChars);
      Serial.write("Data is,");
      //delay(2);
      Serial.write( itoa (RPMout, 4,10)); 
      //delay(2);
      Serial.write(", 30, 48.35");
      //delay(2);
      Serial.write(">");
      //delay(10);
      Serial.println("");
    }
  }   
}

void setup() 
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
  pinMode(ESCPin, OUTPUT);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
  readings[thisReading] = 0; }
  Time = millis();
  ReadInt = -100;
  }


void ReadSensor (){
    // get the sensor value
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(throttle);
  //Serial.println(readings[readIndex]);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;
  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }
  // calculate the average:
  Tavg = total / numReadings;
}


void loop(){
  ReadSensor();
  ReadEnc();
  RPM = 1800;
  Tout = map(Tavg, 180, 860, 0, 200);
  if (Tout>0){
  analogWrite(ESCPin, Tout);
  }

if (Time > ReadInt + 5000) {
  sendData ();  // when this is commented it works fine, tried moving it everywhere
  ReadInt = Time;
  }
  Time = millis();
}

如果有人有任何想法,请告诉我,我知道我可能没有很好地解释我的问题,所以如果他们有任何问题或需要更多详细信息,请询问。

【问题讨论】:

    标签: arduino serial-port arduino-uno


    【解决方案1】:

    itoa 的第二个参数应该是一个指向输出缓冲区的指针。但你不需要itoa。使用Serial.print(RPM);。对于字符串,printwrite 函数是相同的,但对于数字,print 有一个 int 版本

    【讨论】:

    • 你好先生是个传奇!!!我已经尝试了这些更改并且工作起来就像一个魅力,需要稍微修改我的接收代码,因为我在这里和那里丢失了一些数据包。但总而言之,我现在在我的小屏幕上收到我的 RPM :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多