- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Arduino无人机项目,每当输出“加载”时(ESC的“开路”信号输入引脚,甚至接地帽),输入“转向”命令开始出现故障(转到非常低的值<< 1000)。
电机速度是转向命令和 throttle 的函数。 (在这个只有一个电机的测试用例中,如下面的代码所示,unMotorSpeed = unThrottleIn +/- unSteeringIn)
当连接到示波器时,物理输入信号(来自接收器的转向和 throttle )非常好,我什至交换了输入引脚以确保接收器和arduino之间没有问题。问题似乎来自软件,但这没有意义,因为当没有附加“负载”时,输入和输出值都很好且干净。 (我将“负载”放在引号中,因为有时它本质上是一个开路 ->电子速度 Controller (ESC)的超高阻抗输入信号,我什至不接地来完成电路)。
有人可以检查一下代码并看看我是否遗漏了什么吗?
此时,一个稍微快速的解决方法就是不将这些新的故障值写入电机,并在新速度明显低于旧速度时保留旧速度值(并且这些值超过 50khz,所以显然一步的巨大跳跃有点疯狂)。
注意:在代码中,unMotorSpeed 的总输出从servoThrottle 引脚发出。只是我最终没有更改的原始命名...如果您阅读代码并看到所有变量,就很清楚了。
更新:奇怪的是,我只是在没有任何更改的情况下运行了我的设置,一切正常...我多次重新刷新arduino以确保这不是一些幸运的故障,并且它继续工作,一切都设置好了。然后我把 Remote 扔在地上,移动了面包板上的几根电线,在将设置重新组合在一起后,事情又回到了原来的样子。我不知道该怎么办!
// --> starting code found at: rcarduino.blogspot.com
// See related posts -
// http://rcarduino.blogspot.co.uk/2012/01/how-to-read-rc-receiver-with.html
with.html
#include <Servo.h>
// Assign your channel in pins
#define THROTTLE_IN_PIN 3
#define STEERING_IN_PIN 2
// Assign your channel out pins
#define THROTTLE_OUT_PIN 9
//#define STEERING_OUT_PIN 9
// Servo objects generate the signals expected by Electronic Speed Controllers and Servos
// We will use the objects to output the signals we read in
// this example code provides a straight pass through of the signal with no custom processing
Servo servoThrottle;
//Servo servoSteering;
// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define THROTTLE_FLAG 1
#define STEERING_FLAG 2
// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;
// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared;
volatile uint16_t unSteeringInShared;
// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart;
uint32_t ulSteeringStart;
//uint32_t ulAuxStart;
void setup()
{
Serial.begin(9600);
// attach servo objects, these will generate the correct
// pulses for driving Electronic speed controllers, servos or other devices
// designed to interface directly with RC Receivers
servoThrottle.attach(THROTTLE_OUT_PIN);
// using the PinChangeInt library, attach the interrupts
// used to read the channels
attachInterrupt(digitalPinToInterrupt(THROTTLE_IN_PIN), calcThrottle,CHANGE);
attachInterrupt(digitalPinToInterrupt(STEERING_IN_PIN), calcSteering,CHANGE);
}
void loop()
{
// create local variables to hold a local copies of the channel inputs
// these are declared static so that thier values will be retained
// between calls to loop.
static uint16_t unThrottleIn;
static uint16_t unSteeringIn;
static uint16_t difference;
static uint16_t unMotorSpeed; // variable that stores overall motor speed
static uint8_t bUpdateFlags; // local copy of update flags
// check shared update flags to see if any channels have a new signal
if(bUpdateFlagsShared)
{
noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables
// take a local copy of which channels were updated in case we need to use this in the rest of loop
bUpdateFlags = bUpdateFlagsShared;
// in the current code, the shared values are always populated
// so we could copy them without testing the flags
// however in the future this could change, so lets
// only copy when the flags tell us we can.
if(bUpdateFlags & THROTTLE_FLAG)
{
unThrottleIn = unThrottleInShared;
}
if(bUpdateFlags & STEERING_FLAG)
{
unSteeringIn = unSteeringInShared;
}
// clear shared copy of updated flags as we have already taken the updates
// we still have a local copy if we need to use it in bUpdateFlags
bUpdateFlagsShared = 0;
interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
// as soon as interrupts are back on, we can no longer use the shared copies, the interrupt
// service routines own these and could update them at any time. During the update, the
// shared copies may contain junk. Luckily we have our local copies to work with :-)
}
//Serial.println(unSteeringIn);
// do any processing from here onwards
// only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared
// variables unAuxInShared, unThrottleInShared, unSteeringInShared are always owned by
// the interrupt routines and should not be used in loop
// the following code provides simple pass through
// this is a good initial test, the Arduino will pass through
// receiver input as if the Arduino is not there.
// This should be used to confirm the circuit and power
// before attempting any custom processing in a project.
// we are checking to see if the channel value has changed, this is indicated
// by the flags. For the simple pass through we don't really need this check,
// but for a more complex project where a new signal requires significant processing
// this allows us to only calculate new values when we have new inputs, rather than
// on every cycle.
///// if-else chain commented out to determine/prove problem with steering signal --> buggy!
if(unSteeringIn < 1400) // if steering joystick moved left
{
difference = 1400 - unSteeringIn;
if(unThrottleIn - difference >= 0)
unMotorSpeed = unThrottleIn - difference;
}
else if(unSteeringIn > 1550) //if steering joystick moved right (needs to be tweaked, but works for now)
{
difference = unSteeringIn - 1600;
if(unThrottleIn + difference < 2000)
unMotorSpeed = unThrottleIn + difference;
}
else
{
unMotorSpeed = unThrottleIn;
}
//Serial.println(unMotorSpeed);
//Serial.println(unSteeringIn);
//Serial.println(unThrottleIn);
if(bUpdateFlags)
{
//Serial.println(servoThrottle.readMicroseconds());
if(servoThrottle.readMicroseconds() != unMotorSpeed)
{
servoThrottle.writeMicroseconds(unMotorSpeed);
Serial.println(unMotorSpeed);
}
}
bUpdateFlags = 0;
}
// simple interrupt service routine
void calcThrottle()
{
// if the pin is high, its a rising edge of the signal pulse, so lets record its value
if(digitalRead(THROTTLE_IN_PIN) == HIGH)
{
ulThrottleStart = micros();
}
else
{
// else it must be a falling edge, so lets get the time and subtract the time of the rising edge
// this gives use the time between the rising and falling edges i.e. the pulse duration.
unThrottleInShared = (uint16_t)(micros() - ulThrottleStart); // pulse duration
// use set the throttle flag to indicate that a new throttle signal has been received
bUpdateFlagsShared |= THROTTLE_FLAG;
}
}
void calcSteering()
{
if(digitalRead(STEERING_IN_PIN) == HIGH)
{
ulSteeringStart = micros();
}
else
{
unSteeringInShared = (uint16_t)(micros() - ulSteeringStart); // pulse duration
bUpdateFlagsShared |= STEERING_FLAG;
}
}
最佳答案
您应该阅读 AttachInterrupt() 的文档- 在“关于中断服务例程”部分中,它提供了有关从中断调用时某些函数如何行为的信息。对于 micros()
它指出:
micros() works initially, but will start behaving erratically after 1-2 ms.
我认为这意味着 ISR 运行了超过 1 毫秒,而不是一般的 1 毫秒,因此可能不适用于这种情况,但您可能需要考虑如何在 ISR 中进行计时。这是 Arduino 的问题 - 糟糕的文档!
一个可能是原因的明确问题是 unSteeringInShared
是非原子的。它是 8 位硬件上的 16 位值,因此需要多个指令来读取和写入,并且该过程可能会被中断。因此,可以在 loop()
上下文中读取值的一个字节,然后在读取第二个字节之前通过中断上下文更改两个字节,这样您就可以得到两个字节的两半不同的值。
要解决此问题,您可以在读取时禁用中断:
noInterrupts() ;
unSteeringIn = unSteeringInShared ;
interrupts() ;
或者您可以自旋锁定读取:
do
{
unSteeringIn = unSteeringInShared ;
} while( unSteeringIn != unSteeringInShared ) ;
您也应该对 unThrottleInShared
执行相同的操作,尽管尚不清楚为什么您没有看到任何问题 - 这可能不是您当前正在观察的问题,但绝对是任何问题案例。
或者,如果 8 位分辨率足够,您可以将输入编码为原子 8 位值,如下所示:
uint8_t unSteeringInShared ;
...
int32_t timeus = micros() - ulSteeringStart - 1000 ;
if( timeus < 0 )
{
unSteeringInShared = 0 ;
}
else if( timeus > 1000 )
{
unSteeringInShared = 255;
}
else
{
unSteeringInShared = (uint8_t)(time * 255 / 1000) ;
}
当然,将比例从 1000 到 2000 更改为 0 到 255 需要更改其余代码。例如,将 0 到 255 范围内的值 x
转换为伺服脉冲宽度:
pulsew = (x * 1000 / 256) + 1000 ;
关于c - Arduino Drone项目,当输出为 "loaded"(甚至上限为gnd)时,输入 "steering"命令开始出现故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37670899/
在典型的 Scala 上界示例中 abstract class Animal { def name: String } abstract class Pet extends Animal {} c
我有 tstzrange 类型的列(带时区范围的时间戳),我只需要更新此值的上限或下限(并保持包含/排除边界) 我设法改变了 (-infinity,infinity) 与 UPDATE table S
我很好奇 GCD 问题。我正在参加 Coursera 算法工具箱类(class),它指出问题的天真解决方案是: for d from 1 to a+b: if d|a and d|b:
我需要知道是否有东西在两个限制之间,但我在 Playground 上不断遇到相同的 2 个错误,而且我似乎无法在网上找到解决方案。知道如何在 Swift 中做到这一点吗? var upperLimit
什么是快速计算 (long int) ceiling(log_2(i)) 的方法,其中输入和输出是 64 位整数?有符号或无符号整数的解决方案是可以接受的。我怀疑最好的方法是类似于找到的方法 here
lower_bound 是什么意思。如果我不得不猜测,我会回答这个函数在小于请求值的最后一个元素处返回迭代器。但我看到lower_bound 几乎和upper_bound 一样。唯一的区别是在 upp
我有一个曾经是 TreeView 控件的菜单,但现在我想让每个项目更加直观,并向树中的每个对象添加更多信息。 我的第一个意图是制作一个代表项目的用户控件,并在运行时将它们添加到面板中。这是一个好方法吗
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Limiting the max size of a HashMap in Java 当键数超过容量时,如何
我将 time_point 设置为下一个完整的五分钟,这很容易: template using minutes = std::chrono::duration, std::chrono::m
这个问题在这里已经有了答案: Upper bound vs lower bound for worst case running time of an algorithm (3 个答案) 关闭 7
这是代码。结果我得到“4 4”。不明白为什么不是“2 4”(根据下限和上限的定义)。 #include using namespace std; int main() { vector v
我必须检查一个包含平方根的不等式。为了避免由于 float 不准确和舍入导致的不正确结果,我使用 std::nextafter() 来获取上限/下限: #include // DBL_MAX #in
我想将一些小数点后两位的数字四舍五入为 1。然而我总是希望它能进入第一轮amount 列中的数字列表示例 140.08 = 140.1 141.63 = 141.7 如果我使用 round(141.6
我是 jfreechart 的菜鸟,我有一个应用程序可以创建一个运行良好的简单条形图。问题是,我希望所有图表显示 1 到 10 的范围。当图表中的最高值低于该值时,较低的值将成为图表的上限,并且将以不
我对支持向量机有一个担忧,即它们的分类分数:这些分类分数有上限吗?我认为不是,因为 SVM 只是一个超平面,而分数基本上是一个点到该超平面的距离。如果没有限制,一个点可以位于空间中的任何位置,因此距离
我有一个网页,我想将其设计为看起来像一本打开的书,中间有一个折痕/阴影。页面的高度不是固定的,而是灵活的,随着内容的增长而增长。 body 元素具有纸张纹理的背景图像,没有任何阴影。 对于阴影,我的设
如何在运行时更改 python for 循环的上限? 代码, from random import randint lower_limit = 0 higher_limit = 200 step_si
我正在尝试构建一个函数: 接受长度为 n 的正整数列表作为参数, 返回所有长度为 n 的列表,这些列表由具有以下属性的非负整数组成: 对于列表 lst 它认为对于所有索引 i,lst[i] ≤ upp
我正在尝试查询我的数据库 ratingsChoices= m$distinct({'answers'}) 但我收到了一个警告:错误:明显太大,16mb 上限 在 mongolite 中有解决这个错误的
我有一个 Mongodb 集合。简单地说,它有两列:用户和网址。它有 39274590 行。该表的键是 {user, url}。 使用 Java,我尝试列出不同的 url: MongoDBMana
我是一名优秀的程序员,十分优秀!