我无法让旋转编码器与AVR微控制器一起正常工作.编码器是机械ALPS编码器,我使用的是Atmega168.
澄清
我曾尝试使用外部中断来收听引脚,但看起来它太慢了.当引脚A变为高电平时,中断程序开始,然后检查引脚B是否为高电平.我们的想法是,如果引脚B变高,引脚A变高,那么它就会逆时针旋转.如果引脚B为低电平,则它按顺时针方向旋转.但似乎AVR检查引脚B需要太长时间,所以它总是读得很高.
我还尝试创建一个程序,只需阻塞直到引脚B或引脚A发生变化.但可能是旋转编码器时噪音太大,因为这也不起作用.我的最后一次尝试是有一个计时器,它将最后8个值存储在缓冲区中,并检查它是否从低到高.这也不起作用.
我已经尝试过对编码器进行范围设计,它似乎在第一个Pin的2到4ms之间使用,直到另一个Pin发生变化.
我正在使用Yosemite OS X在Mac上工作,我正在尝试用C编译一个程序,然后我可以上传到我的Arduino.我正在学习一个教程.
我试过并重新安装avr-gcc,但我得到了相同的输出.我尝试crtatmega328p.o在我的系统上搜索该文件,但它无处可寻,目录也是如此.
$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o Program.o Program.c
$ avr-gcc -mmcu=atmega328p Program.o -o Program
/usr/local/lib/gcc/avr/5.2.0/../../../../avr/bin/ld: cannot find crtatmega328p.o: No such file or directory
/usr/local/lib/gcc/avr/5.2.0/../../../../avr/bin/ld: cannot find -latmega328p
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud) 我想使用Arduino作为i2c奴隶.但我要求Arduino通过向多个i2c地址注册来充当多个设备.
这可能不是人们通常会做的事情,但这是我做这件事的原因:
我想用Arduino作为Spektrum遥测的遥测传感器.遥测接收器有一些i2c插头,连接到多个传感器(电流0x02,电压0x03,空速0x11等),每个传感器都具有遥测接收器所需的固定i2c地址.
我想使用一个 Arduino作为所有这些设备,通过注册所有上述地址,并适当地响应读数.
我可以使用每个传感器一个Arduino,这看起来很傻,因为我可以使用一个Arduino pro-mini执行所有这些读数.
我知道你可以使用注册Arduino
Wire.begin(0x02);
Run Code Online (Sandbox Code Playgroud)
但是我需要类似的东西(伪代码)
Wire.begin(0x02, 0x03, 0x11);
Run Code Online (Sandbox Code Playgroud)
当收到请求时,我需要知道Arduino被查询的地址.
例如(伪代码)
void receiveEvent(byte address, int bytesReceived){
if(address == 0x02){
// Current reading
}
else if(address == 0x03){
// Voltage reading
}
else if(address == 0x11){
// Airspeed reading
}
}
Run Code Online (Sandbox Code Playgroud)
任何意见,将不胜感激.
这是官方ATMEGA328p数据表第261页的摘录:
正如文档所说
Vin * 1024
ADC = ----------
Vref
Run Code Online (Sandbox Code Playgroud)
我不明白的是,一个模拟引脚可以为我们提供10位。这意味着0x0到0x3ff之间的值(1023)
所以我不明白为什么文档会说Vin * 1024而不是1023。因为对我来说0v = 0和5v = 1023?
我必须做一些需要使用三角函数的计算,特别是那个atan.代码将在Atmega328p上运行,为了提高效率,我不能使用floats:我使用的是定点数.因此,我无法使用标准atan功能.
我有一个函数,它采用定点格式的值s16_10(有符号,16位宽,第10位),并返回s16_6格式.输入将介于0和1之间(因此为0和2 10),因此输出(以度为单位)将介于-45和45之间(因此-45*2 6和45*2 6).
假设Y是固定点,y是s16_6表示,弧的实际角度,x是x atan(x) = y,X是s16_10的x表示.我从使用atan4度多项式近似函数,从(0,1)到(-45,45)开始,发现我们可以使用:
y ~= 8.11 * x^4 - 19.67 * x^3 - 0.93 * x^2 + 57.52 * x + 0.0096
Run Code Online (Sandbox Code Playgroud)
这导致:
Y ~= (8.11 * X^4)/2^34 - (19.62* X^3)/2^24 - (0.93 * X^2)/2^14 + (57.52*X)/2^4 + 0.0069 * 2^6
Run Code Online (Sandbox Code Playgroud)
在这里我被卡住了......一方面,计算X^4将导致定义间隔的五分之一为0,另一方面,{ 3,2,1 }中的2 n4 n通常也会导致零价值......我怎么办?
最近我试图将我的代码打包到带有 1kB 闪存的小型 ATTiny13 中。在优化过程中,我发现了一些奇怪的东西。让我们以示例代码为例:
#include <avr/interrupt.h>
int main() {
TCNT0 = TCNT0 * F_CPU / 58000;
}
Run Code Online (Sandbox Code Playgroud)
它当然没有意义,但有趣的是输出大小 - 它产生248 bytes。
代码快速说明:F_CPU是由-DF_CPU=...switch for定义的常量avr-gcc,TCNT0是 8 位寄存器(在 ATTiny13 上)。在实际程序中,我将方程结果分配给uint16_t,但仍然观察到相同的行为。
如果表达式的一部分被括在括号中:
TCNT0 = TCNT0 * (F_CPU / 58000);
Run Code Online (Sandbox Code Playgroud)
输出文件大小为70 字节。巨大的差异,但这些操作的结果是相同的(对吧?)。
我查看了生成的汇编代码,尽管我不太了解 ASM,但我看到无括号版本添加了一些标签,例如:
00000078 <__divmodsi4>:
78: 05 2e mov r0, r21
7a: 97 fb bst r25, 7
7c: 16 f4 brtc .+4 ; 0x82 <__divmodsi4+0xa>
7e: 00 94 …Run Code Online (Sandbox Code Playgroud) 我有一个新的 stk500v2 编程器(Pololu),想读取 atmega8 的保险丝。对于我的老程序员,我使用命令
avrdude -v -p atmega8 -P /dev/cu.usbmodem002938642 -c stk500v2
Run Code Online (Sandbox Code Playgroud)
并在 2 行上得到了 lfuse 和 hfuse
现在我只得到
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9307 (probably m8)
Run Code Online (Sandbox Code Playgroud)
使用
avrdude -v -p atmega8 -P /dev/cu.usbmodem002938642 -c stk500v2 -U hfuse:r:-:h
Run Code Online (Sandbox Code Playgroud)
我明白了
avrdude: reading hfuse memory:
Reading | ################################################## | 100% 0.00s
avrdude: writing output file "<stdout>"
0xd9
Run Code Online (Sandbox Code Playgroud)
与 lfuse 相同。有没有办法使用相同的命令获取 hfuse 和 lfuse ?
标题说明了一切.如何检测Arduino中按下/释放按钮的时间长度,然后打印一些自定义输出?
注意:
有人在我面前问了这个问题,我回答.然而,在我发送答案之前,这个人删除了他自己的问题.我只是重新问了所以我可以发布已经写好的答案(希望它可以帮助其他人).
我编写了以下代码,以使ATMEGA168A闪烁一个小的led:
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000UL
int main(void)
{
DDRB = 0b00000010;
PORTB = 0b00000000;
while(1)
{
PORTB ^= 1 << 1;
_delay_ms(1000);
}
}
Run Code Online (Sandbox Code Playgroud)
编译器向我发出如下警告:
Warning #warning "F_CPU not defined for <util/delay.h>"
Run Code Online (Sandbox Code Playgroud)
这是此警告的来源(delay.h)
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么?我的声明不正确吗?
让我说我有uint8_t bytes[maxBytes];.
现在我想比较第一个字节(bytes[0])的低6位0x3c.
我试着这样做:
bytes[0] & 0x3f == 0x3c
Run Code Online (Sandbox Code Playgroud)
不幸的是,这并没有产生预期的结果.(即它总是假的,即使我打印出来的bytes[0] & 0x3f时候也是如此0x3c)
我已经玩了一些这个,并发现了
bytes[0] & 0x00 == 0x00
Run Code Online (Sandbox Code Playgroud)
有时是真的,有时是假的.(与bytes[0] & 0x0 == 0x0和相同bytes[0] & 0x00 == 0x0).它不应该永远是真的吗?
这里发生了什么?我怎样才能进行0x3c比较?
Sitenote:我在arduino w/atmega328pb MCU上运行此代码.