【发布时间】:2017-02-24 17:02:25
【问题描述】:
我正在尝试使用 arduino yun 将机器生产的零件数量输出到谷歌电子表格。通过我的设置,我可以暂时将数据输出到电子表格。然而,过了一段时间,云停止了工作。我用来指示代码正在运行的红色 LED 熄灭了,我再也看不到端口列表中的 arduino。 32u4芯片复位导致LED重新亮起,表示代码正在运行,但板子仍然没有出现在端口菜单中。
我已经在我们的车间对其进行了测试,它已经运行了 7-12 个小时,完全没有问题。只有当我们把它带到生产车间时,我们才开始遇到这些问题。有谁知道问题可能是什么?这是代码中最相关的部分:
#include <elapsedMillis.h>
#include <Process.h>
#include <Bridge.h>
#include "TimeLib.h"
// On Arduino: 0 - 1023 maps to 0 - 5 voltsf
#define VOLTAGE_MAX 5.0
#define VOLTAGE_MAXCOUNTS 1023.0
unsigned int buttonCount = 0;
float voltage = 0;
elapsedMillis timeSinceLastCycle = 0;
elapsedMillis transmitData = 0;
int pressFlag = 0;
Process date;
int hours, minutes, seconds;
int lastSecond = -1;
Process sendData;
String printDate() {
// String currTime = String(hours) + ":" + String(minutes) + ":" + String(seconds);
if (lastSecond != seconds) { // if a second has passed
// print the time:
if (hours <= 9) {
Console.print("0"); // adjust for 0-9
}
Console.print(hours);
Console.print(":");
if (minutes <= 9) {
Console.print("0"); // adjust for 0-9
}
Console.print(minutes);
Console.print(":");
if (seconds <= 9) {
Console.print("0"); // adjust for 0-9
}
Console.println(seconds);
// restart the date process:
if (!date.running()) {
date.begin("date");
date.addParameter("+%T");
date.run();
}
}
//if there's a result from the date process, parse it:
while (date.available() > 0) {
// get the result of the date process (should be hh:mm:ss):
String timeString = date.readString();
// find the colons:
int firstColon = timeString.indexOf(":");
int secondColon = timeString.lastIndexOf(":");
// get the substrings for hour, minute second:
String hourString = timeString.substring(0, firstColon);
String minString = timeString.substring(firstColon + 1, secondColon);
String secString = timeString.substring(secondColon + 1);
// convert to ints,saving the previous second:
hours = hourString.toInt();
minutes = minString.toInt();
lastSecond = seconds; // save to do a time comparison
seconds = secString.toInt();
String currTime = hourString + ":" + minString + ":" + String(seconds);
return currTime;
}
}
void checkVoltage() {
int sensorValue = analogRead(A0);
voltage = sensorValue * (VOLTAGE_MAX / VOLTAGE_MAXCOUNTS);
Console.println(voltage);
delay(50);
if (voltage >= 4.9 && pressFlag == 0) {
Console.println("Delaying");
sensorValue = analogRead(A0);
voltage = sensorValue * (VOLTAGE_MAX / VOLTAGE_MAXCOUNTS);
if (pressFlag == 0 && voltage >= 4.9) {
unsigned long int intCycleTime = timeSinceLastCycle;
timeSinceLastCycle = 0;
digitalWrite(LED_BUILTIN, LOW); // turn the LED on (HIGH is the voltage level)
printDate();
String pressTime = printDate();
Console.print("PressTime is ");
Console.println(pressTime);
buttonCount++;
Console.println(buttonCount);
pressFlag = 1;
String part1 = "curl -X POST -H \"Content-Type: application/json\" -d '{\"value1\":\"";
String timeString = pressTime;
Console.print(timeString + " seconds");
String part2 = "\",\"value2\":\"";
String numParts = String(buttonCount);
String part3 = "\",\"value3\":\"";
String strCycleTime = String(intCycleTime / 1000); // + " seconds";
String part4 = "\"}' https://maker.ifttt.com/trigger/arduino2Request/with/key/gL8YmxeaUChOMJvmwpdXp -k";
//curl -X POST -H "Content-Type: application/json" -d '{"value1":"1","value2":"2","value3":"3"}' https://maker.ifttt.com/trigger/arduino2Request/with/key/gL8YmxeaUChOMJvmwpdXp
String curlString = part1 + timeString + part2 + numParts + part3 + strCycleTime + part4;
// The curl string sends data to oue excel spreadhsheet using the IFTTT web service
sendData.runShellCommandAsynchronously(curlString);
elapsedMillis breakTimer = 0;
/*while(sendData.running()){
if(breakTimer > 5*1000){
break;
}
} */
Console.print("Data Available: "); // A value of 32 indicates a successful transmission of data, 0 also works if run asynchronously.
Console.println(sendData.available());
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
}
}
else if (voltage < 2.5) {
pressFlag = 0;
}
}
void setup() {
Bridge.begin();
Console.begin();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
// run an initial date process. Should return:
// hh:mm:ss :
if (!date.running()) {
date.begin("date");
date.addParameter("+%T");
date.run();
}
}
void loop() {
checkVoltage();
if ((timeSinceLastCycle > 300000) && (transmitData > 300000)) { // If 5 minutes have elapsed without a part being produced, output that the arduino is transmitting even if not part is available
sendData.runShellCommand("curl -X POST -H \"Content-Type: application/json\" -d '{\"value1\":\"1\",\"value2\":\"Arduino Transmitting\"}' https://maker.ifttt.com/trigger/transmitData/with/key/gKRo-zSur5rj6rD5rviCaV2RHI5g56Dy0Vc0S_XJ-oO -k");
transmitData = 0;
}
}
更新:我在 checkVoltage 函数中添加了一系列打印语句。上面的代码已更新以反映这一点。我发现它在尝试使用 sendData.runShellCommandAsynchronously 时挂起。输出看起来像
1.58
1.54
5.00
Delaying
PressTime is n" -d
3
尝试运行ShellCommand 时网络连接中断会导致此问题吗?
【问题讨论】:
-
我可以看到随着时间的推移出错的事情之一是
buttonCount溢出。反正代码是不完整的。 -
问题是,在溢出成为问题之前,它会失败很长一段时间。此外,我并不关心 buttonCount 的确切值,因为我的数据处理脚本只检查是否有一个数字并自己再次计算条目。这可以防止机器在短时间内断电并且值重置为 0 时出现错误计数。我已更新代码以包含完整代码。
-
有一些明显的差距,特别是在 printDate 函数中,因为我之前有打印语句。我把它们拿出来希望缩小代码可以解决我的问题,但没有运气
-
我喜欢这个问题。与生产线相比,您在车间用多少个项目进行了测试?我要检查的第一件事是动态内存,它被
String及其+运算符隐式使用。您可以更有效地使用闪存中的单个静态分配的 char[] 缓冲区 +sprintf()+ 存储在 PROGMEM 中的单个格式字符串(请参阅:this)。您可以使用存储值限制轻松计算命令的最大长度。 -
printDate()的签名说它返回一个char *,但是,有一条通过代码的路径不返回任何内容。 (当没有输入while()时。编译器应该会抱怨。编译时,始终启用所有警告,然后修复这些警告。(对于gcc,至少使用:-Wall -Wextra -pedantic我也使用:@987654333 @)
标签: c arduino arduino-yun