我正在尝试修改此代码,以使其在 Arduino Mega 上运行。我对 C 还很陌生,所以我可能犯了一些重大错误。顺便说一下,这是一个自平衡滑板。:P

此代码取自 ATmega32(来自:[网址=http://sites.google.com/site/onewheeledselfbalancing/Home/twin-wheel-self-balancing-skateboard-lightweight-version/code4]http://sites.google.com/site/onewheeledsel...t-版本/代码4[/url] 我正在尝试让它在 Arduino Mega 上工作。

该代码是为 ATmega32 开发板编写的http://www.active-robots.com/products/controllr/m32db.shtml

谢谢你!

这是我遇到的第一个错误:

在函数“voidtimer_init()”中:错误:TCCR0 "未在 this scope 在函数 "int main() "中:

有人可以解释一下我出了什么问题吗?我几乎是编程的初学者,但我读了很多书籍/网站,而且我学得也很快!^^ 下面是完整的代码(相当长):

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <math.h>

定义 CLOCK_SPEED 16000000

定义 OCR1_MAX 1023

typedef 无符号字符 u8;空白 set_motor_idle(void);空白 InitPorts(void);浮动水平=0;浮动 油门踏板浮动aa;浮动 加速;浮动x_acc;浮动累加;浮动x_accdeg;

浮动陀螺;

浮动ganglerateg;浮动 gangleraterads;浮动ti = 2.2;

浮动总增益;浮动增益控制;浮动电池电压 = 24;浮动 gyroangledt;浮动角度;浮动 anglerads;浮动平衡扭矩;浮动 软启动;

浮动当前速度;float cycle_time = 0.0064;浮动平衡点;浮点数 a0、a1、a2、a3、a4、a5、 a6;//Savitzky-Golay variables for 加速计

整数我;整数j;int 提示开始;空白 InitPorts(void) { PORTC=0x00;//端口 C 上拉设置为低电平(无输出 电压),以 DDRC=0xFF 开始;//端口 C 的所有引脚都被设置为输出。 端口 C 方向寄存器 //PORTC |= (1<

DDRA=0x00;// 所有端口 A 引脚设置为 输入 PORTA=0x00;//端口 A 输入 拉升设置为低拉升

DDRD=0xFF;/配置所有端口 D 引脚 作为 OCR1A 的先决条件输出 (引脚 D5)和 OCR1B(引脚 D4)工作。 正确

端口B=0x00;//端口 B 上拉设置为 低(无输出电压)开始 DDRB=0xFF;//所有端口 B 引脚都设置为 产量

/* IO:我使用的是频率为 16MHz 的 ATMega32 带外部晶体时钟。新 OSMC 电机的计划引脚排列 控制器 PC4 板载 LED PD5/OC1A ALI -> OSMC 第 6 针 PD4/OC1B BLI -> OSMC 第 8 针 PC1 禁用 -> OSMC 第 4 针 PC2 BHI -> OSMC 第 7 针 PC3 AHI -> OSMC 第 8 针 OSMC 引脚 5 PA6/ADC6 Vbatt/10 -> OSMC 第 3 针 PA1/ADC1 螺距速率陀螺仪 PA0/ADC0 加速计 / void adc_init(void){ / 熄灭 模拟比较器,因为我们不使用它 / 钢芯铝绞线 = (1 << ACD);/ 选择PA0 / ADMUX = 0;ADMUX |=(1< 设置 ADC 将预分频器设置为 128,启用 ADC,然后 开始转换 / adcsra = 0 | (1 < / 等到假的第一次转换 完成 */ while (ADCSRA & (1 <<) ADSC)) { } }

uint16_t adc_read(uint8_t 通道) {
/* 选择频道 / ADMUX = 渠道;ADMUX |=(1< 开始转换 /
ADCSRA |= (1 << ADSC);/
等到 转换完成 / while(adcsra&(1 << adsc)){} / 返回 result */ 返回 ADCW;}

/* 每秒 156 个周期,每个周期 6.4ms 在振荡仪上测量*/ /* 全部读取 ADC 输入并进行一些转换 */ void sample_inputs(void) {

uint16_t adc0, adc1, adc2, adc3, adc4, adc5;
 gyrosum=0;   adc0 = adc_read(0); /* accelerometer pin PA0 */   accelraw

=(浮点数)adc0;对于 (j=0;j<7;j ) { adc1 = adc_read(1);//陀螺仪引脚 PA1 gyrosum = (float) gyrosum adc1;//使用每个样本 7 个样本的平均值 陀螺仪的循环,这样它就能获得 的每个循环完成更新 程序 }

adc2 = adc_read(2); /* grey wire overallgain (via cutout switch)

位置 PA2*/ adc3 = adc_read(3);/* 定位杆拉回位置 PA3*/ adc4 = adc_read(4);/* 节气门踏板位置 PA4*/ adc5 = adc_read(5);/* 按下定位杆 前移位置 PA5*/ //adc6 = adc_read(6);/* 来自 OSMC 的 Vbatt 输入 (目前未使用) 位置 PA6*/ //仅对 a0 = a1 进行加速的 Sav Golay 滤波器;a1=a2;a2=a3;a3 = a4;a4 = a5;a5 = a6;a6 = (float) accelraw;accsum = (float) ((-2*a0) (3*a1) (6*a2) (7*a3) (6*a4) (3*a5) (-2*a6))/21;//Sav 戈莱计算

    gaincontrol = (float) gaincontrol*0.9 + 0.1*adc2/341;

//平滑任何电压尖峰并提供 范围 0-3 Throttle_pedal=(float) Throttle_pedal*0.9 0.1*adc4/341;//平滑任何电压尖峰并提供 范围 0-3

//切断电机,如果死人 释放按钮 //(gaincontrol 变量也通过这个 按钮到 adc2 如果 (adc2<100) { Throttle_pedal=0.001;增益控制=0.001;} 总增益 = 增益控制 * 软启动;//如果杠杆向后拉或向前推或不做,该怎么办? 什么都可以平衡点=514;如果 (adc3>100) Balance_point=534;

如果 (adc5>100) Balance_point=494;

 PORTB |= (1<<PB2);//Port B2 turned on/off once per loop so I can

用示波器测量循环时间

/加速度计信号处理/ /减去偏移量/ x_acc=(float) accsum - Balance_point;//accsum 是 SG 值 加速度计,而不是真正的 "总和",因此 无需除以 7 如果 (x_acc<-250) x_acc=-250;//上限加速度值范围为 -250 至 250(各倾斜 80 度),如果 (x_acc>250) x_acc=250;/* 加速度计每倾斜一度,角度变化约为 3.45 个单位。 范围 0-30°(正弦θ) 转换 倾斜度从 加速度传感器。正弦角度 大致 = 小角度的角度,因此 无需计算三角函数。x_acc 下面的单位现在是摄氏度*/

x_accdeg=(浮点数)x_acc/-3.45;//减号用于校正背面 到前加速度计安装位置!

  /*GYRO signal processing*/
 /*Subtract offsets: Sensor reading is 0-1024 so "balance point"

IE。我所需的零点将是 读数减去 512*/

/陀螺仪角度每度变化 20mV 根据数据表,每秒的变化量为 4.每秒角度变化 096 个单位(0 - 1023)/度 This 限制陀螺仪的变化率 角度刚好小于最大 它的实际能力 测量(100 度/秒)。注意所有这些 小数四舍五入为整数 稍后,就在它被发送到 PWM 发生器 连接至电机控制器/ gangleratedeg=(float)((gyrosum/7) - 508)/4.096;//gyrosum是一组7个样本的总和,因此除以7表示 陀螺仪值,如果 (gangleratedeg < -92) angleratedeg=-92;如果(ganglerateg

92) ganglerateg=92 /我在每个主程序中开关一次端口 B2 周期,这样我就可以连接示波器 并制定出程序周期 我使用周期时间来计算 陀螺仪每个周期的角度变化 要知道这段时间有多长 间隙/ 端口 B &= (0<

/ti 表示 "i "的缩放 或积分系数(目前为 2.2 这里)gyroangledt 是角度变化 自上一 CYCLE 以来,陀螺仪的度数 传感器,其中 ti 是缩放因子 (理论上应约为 1,但 2.2 使木板感觉更紧)
帮派现在以度为单位 每秒 常数,即较小的 aa 值会使 加速度计时间常数变长 它会慢慢纠正陀螺仪 飘移
/

aa=0.005;陀螺角=(浮点)ti周期ganglerateg;
gangleraterads=(浮点)ganglerateg*0.017453;

/新角度(度)等于旧角度 加上陀螺仪的角度变化,因为 上一轮,有一点新 加快阅读速度/ 角度 = (float)((1-aa) * (angle gyroangledt)) (aa * x_accdeg);// 主角度计算函数*/ //Convert 从度到弧度的角度

 anglerads=(float)angle*0.017453;
      balance_torque=(float)(4.5*anglerads)

+ (0.5*gangleraterads);

cur_speed = (float)(cur_speed ) (Throttle_pedal * balance_torque *) cycle_time)) * 0.999;

/* 级别值从 -1 到 1 不等,并且 表示要发送的占空比 连接到电机。转换为弧度 帮助我们不超出这些限制 电平 = (balance_torque cur_speed) * 总增益;

}

void Timer_init(){tccr0 = 0 | (1

// PWM 模式为 "PWM,相位校正"、 10 位" TCCR1A = 0 | (1<)

(1<

无效set_motor()

/* 水平项是水平项 从 -1023 重新调整为 1023 作为 准备发送至 PWM 电机的整数 控制端口,这些端口又 连接到 OSMC*/ {

//if (level<-0.9) level= -0.9;//checks we are within sensible limits //if (level>0.9) level=0.9;

int16_t leveli = (int16_t)(level*1023);//注意这里我们 取浮点数,我们得到 级 "的结果,我们乘以 乘以 1023,然后将其转化为 整数,然后将数值输入 PWM 发生器为 "leveli"。

如果 (leveli<-1020) leveli=-1020;//双重检查我们是 在合理的 PWM 限制范围内,因为不 想突然被抛下 board if (leveli>1020) leveli=1020;

/将端口 B1 上的 LED 或蜂鸣器设置为 警告我慢下来,如果扭矩是 交付量超过最大值的 50 原因是 你总是需要一些备用电机 以防万一 如果电机已 你将会 高速翻倒!有的使用 自动提示返回例程,以自动 限制最高速度。现在我来做 这样更容易/

if (级别<-0.7 || 级别>0.7) {
PORTB |= (1< PORTB &= (0<

软启动=(浮动)软启动+0.001;如果(软启动>1.0)软启动=1.0;

//PORTC |= (0<<PC1);   // AHI=1  PinC3, BHI=1 PinC2 set both to ON for

将 OSMC 调至工作状态,并将两者都调至关闭状态以关闭 电机下降 /*注意不知道为什么,但为了 停止电机按方向运转 我最后不得不硬接线 AHI 和 BHI 至 12V / / 未禁用 通过将 PinC1 输出设置为零,OSMC 就可以运行、 1 将禁用 OSMC*/ PORTC |= 0x0c;//make C1 pulled down so 取消禁用 OSMC,即启用它。PORTC &= ~0x02;//如果 (leveli<0) { OCR1A = -leveli;// ALI 是 PWM 倒退,因为电平变量是 为负符号值时,保留 负号在此登录!OCR1B=0;// BLI = 0 } 否则 { OCR1A = 0;// ALI = 0 作为水平线前进 变量为正符号值 OCR1B = leveli;// BLI 是 PWM } }

int main(void){initports();

adc_init();

定时器_init();

/* 初始倾斜启动代码 打开 微,同时木板向一侧倾斜、 骑手即将踏上它,如果倾斜 角度越过零点(中点)平衡 算法开始运行 否则将永远被锁定在这个循环中 直到倾斜到水平位置 当骑手登上滑板时*/ tipstart=0;加速原始=0;

而(提示开始<1){

// 您需要它来允许 SG 将过滤器卷绕到适当的稳定位置 首次开机时的值、 的值之前 (下图)。

对于 (i=0;我<20;我++){
样本输入();
}

if (accsum<504 || accsum>524) { //
如果 (x_accdeg>0) { 提示开始 = 0;} 否则 { tipstart=1;
软启动=0.4;} }

角度=0;当前速度=0;/* 倾斜结束 启动代码。如果超过这一点 则机器变平,并 活动*/

sei();

while (1) { 样本输入();

设置电机();

} }

有帮助吗?

解决方案

您很可能为您的构建指定了错误的 MCU。虽然 Arduino Mega 上的 ATmega1280 上存在 DDRA,但常规 Arduino 的 ATmega328 上不存在 DDRA。

如果您使用的是 Arduino UI,请转到工具 | 板,然后选择 Arduino Mega。

如果您使用自己的构建系统,则需要更新在 gcc 命令行上为 -mmcu= 指定的值。

其他提示

我想你可能在这里留下了结束评论:

/*The level value is from -1 to +1 and represents the duty cycle to be sent to the motor. Converting to radians helps us stay within these limits >>>*/<<<

当编译器告诉您某些内容“未在此范围内声明”时,请像您自己一样提出这个问题:

什么范围 曾是 声明于?

如果你不能回答这个问题,那么你就发现了问题。毕竟,如果 不知道这个名字指的是什么,你怎么能指望编译器呢?请记住 是任何代码的专家 写。

如果你 确定该事物在哪个范围内声明,那么下一个任务是确定该范围与您尝试使用它的范围如何相关。典型问题包括(但不限于)以下内容:

  • 它是在其他一些命名空间中声明的。使用 :: 范围解析运算符给出完全限定的名称。
  • 它被声明为类的成员,并且您尝试在独立函数中使用它。找到类的实例并通过该对象访问变量或函数,或者更改类以将新函数作为其成员之一。

如果你 不能 找到它声明的范围,那么有一些可能是错误的:

  • 你拼写错了。检查文档中的拼写并修复您的代码。
  • 它是在您忘记包含的某些标头中声明的。找出它的声明位置并添加适当的 #include 指示。 这可能是您的情况的问题。
  • 它没有在任何地方声明。弄清楚它在哪里 应该 被声明并自己在那里声明。

这里是一个相当简单的 Arduino 代码的链接,用于控制 DIY 赛格威。

我认为这对于你的滑板来说是一个更好的起点。

http://diysegway.blogspot.com/

最好的祝愿

约翰

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top