1

Arduino Megaで動作するように、このコードを変更しようとしています。私はCにかなり慣れていないので、いくつかの大きな間違いを犯した可能性があります。ちなみに、これはバランススクーター用です。:P

このコードはATmega32から取得されます(from:[url = http://sites.google.com/site/onewheeledselfbalancing/Home/twin-wheel-self-balancing-skateboard-lightweight-version/code4 ] http:// sites .google.com / site / onewheeledsel ... t-version / code4[/url] そして私はそれをArduinoMegaで動作させようとしています。

このコードはATmega32開発ボード用に書かれました http://www.active-robots.com/products/controllr/m32db.shtml

ありがとうございました!

これが私が遭遇する最初のエラーです:

関数'voidtimer_init()':エラー:'TCCR0'はこのスコープで宣言されていません関数'int main()':

誰かが私に何が悪いのか説明してもらえますか?私はプログラミングの初心者ですが、たくさんの本やウェブサイトを読んだことがあり、私も速く学んでいます!^^そしてここに完全なコードがあります(かなり長いです):

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

CLOCK_SPEED16000000を定義します

OCR1_MAX1023を定義します

typedef unsigned char u8; void set_motor_idle(void); void InitPorts(void); フロートレベル=0; float Throttle_pedal; フロートaa; フロートアクセラウ; float x_acc; フロートアキュム; float x_accdeg;

フロートジャイロサム;

float gangleratedeg; フロートgangleraterads; float ti = 2.2;

フロート全体ゲイン; フロートゲインコントロール; フロートバッテリーボルト=24; フロートジャイロアングルdt; フロート角度; フロートアングルラッド; float balance_torque; フロートソフトスタート;

float cur_speed; float cycle_time = 0.0064; float Balance_point; float a0、a1、a2、a3、a4、a5、a6;//加速度計のSavitzky-Golay変数

int i; int j; int tipstart; void InitPorts(void){PORTC = 0x00; // DDRC = 0xFFで開始するためにポートCプルアップを低(出力電圧なし)に設定。//ポートCピンはすべてポートC方向レジスタを介して出力として設定されます//PORTC| =(1 <

DDRA = 0x00; //入力として設定されたすべてのポートAピンPORTA=0x00; //ポートAの入力プルアップが低プルアップに設定されている

DDRD = 0xFF; // OCR1A(PinD5)およびOCR1B(Pin D4)が正しく機能するための前提条件として、すべてのポートDピンを出力として構成します

PORTB = 0x00; //ポートBのプルアップを低(出力電圧なし)に設定して、DDRB=0xFFで開始します。//すべてのポートBピンを出力に設定

} / * IO:外部水晶クロックでATMega3216MHzを使用しています。OSMCモーターコントローラーPC4オンボードLEDPD5/ OC1AALI->OSMCピン6PD4/ OC1BBLI->OSMCピン8PC1無効->OSMCピン4PC2BHI->OSMCピン7PC3AHI->OSMCピン5への新しい計画されたピン配置PA6 / ADC6 Vbatt /10->OSMCピン3PA1/ADC1ピッチレートジャイロPA0/ADC0加速度計 /voidadc_init(void){//使用しないのでアナログコンパレータをオフにする /ACSR =(1 << ACD); / PA0 / ADMUX=0を選択します。ADMUX | =(1 <ADCプリスケーラを128に設定し、ADCを有効にして、変換を開始します/ ADCSRA = 0 |(1</偽の最初の変換が終了するまで待ちます*/ while(ADCSRA&(1 <<

uint16_t adc_read(uint8_t channel){
/*チャネルを選択/ADMUX=チャネル; ADMUX | =(1<変換の開始/
ADCSRA | =(1 << ADSC);/
変換が終了するまで待つ/while(ADCSRA&(1 << ADSC)){}/結果を返す*/ADCWを返す;}

/ * 156サイクル/秒、6.4ms/サイクルOSCILLOSCOPEで測定*/ / *すべてのADC入力を読み取り、変換を実行* / void sample_inputs(void){

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

=(float)adc0; for(j = 0; j <7; j ++){adc1 = adc_read(1); //ジャイロピンPA1gyrosum=(float)gyrosum + adc1; //ジャイロのループごとに平均7つのサンプルを使用して、プログラムの各ループで完全な更新を取得します}

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

位置PA2*/ adc3 = adc_read(3); /*ポジションレバーを引き戻した位置PA3*/ adc4 = adc_read(4); /*Throttle_pedalの位置PA4*/ adc5 = adc_read(5); /*位置レバーを前方に押して位置PA5*/ // adc6 = adc_read(6); / * OSMCからのVbatt入力(現在は使用されていません)位置PA6 *///加速のみのSavGolayフィルターa0=a1; 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; //SavGolayの計算

    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に配線されますif(adc2 <100){Throttle_pedal = 0.001; gaincontrol = 0.001;} totalgain = gaincontrol * softstart; //レバーが後ろに引っ張られたり、前に押されたり、何もしなかった場合の対処方法:Balance_point = 514; if(adc3> 100)Balance_point = 534;

if(adc5> 100)Balance_point = 494;

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

オシロスコープでループ時間を測定する

/ ACCELEROMETER信号処理//オフセットの減算/ x_acc=(float)accsum-Balance_point; // accsumは加速度計のSG値であり、真の「合計」ではないため、7で割る必要はありませんif(x_acc <-250)x_acc = -250; //加速値を-250〜 + 250の範囲に制限します(片道80度傾斜)if(x_acc> 250)x_acc = 250; / *加速度計の角度変化は、0〜30度(正弦波)の範囲で1度の傾斜あたり約3.45単位です。傾斜を加速度センサーからの傾斜度に変換します。正弦角=おおよそ=小さな角度の角度なので、三角法を実行する必要はありません。以下のx_accはDEGREES*/になりました

x_accdeg =(float)x_acc / -3.45; //マイナス記号は、後ろから前への加速度計の取り付けを修正します!

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

つまり、必要なゼロ点は、読み取り値から512*/を引いた値になります。

/データシートからの毎秒20mVのジャイロ角度の変化は毎秒4.096単位(0〜1023のスケールで)の変化を与えます角度の変化これはジャイロ角度の変化率を最大速度よりわずかに小さく制限します実際に測定可能(100度/秒)。これらの小数部はすべて、PWMジェネレーターに送信される直前に整数に切り上げられ、PWMジェネレーターはモーターコントローラーに接続されます/ gangleratedeg =(float)((gyrosum / 7)-508)/4.096; //ジャイロサムは7つのサンプルのグループの合計であるため、ジャイロ値を7で割るとif(gangleratedeg <-92)gangleratedeg = -92; if(gangleratedeg

92)gangleratedeg = 92 /メインプログラムサイクルごとに1回ポートB2のオンとオフを切り替えて、オシロスコープを接続してプログラムサイクルタイムを計算できるようにします。サイクルタイムを使用して、サイクルごとのジャイロ角度の変化を計算します。この時間間隔の長さを知る/PORTB&=(0 <

/ tiは、「i」または積分係数(現在は2.2)のスケーリングを表します。ジャイロアングルdtは、ジャイロセンサーからの度数で表した最後のCYCLE以降の角度変化です。ここで、tiはスケーリング係数です(理論的には約1である必要がありますが、2.2はボードをよりタイトに感じさせます
)現在、度/秒の単位でaaは時定数を変化させます。つまり、aa値が小さいほど、ジャイロドリフトをゆっくりと補正するため、加速度計の時定数が長くなります

aa = 0.005; gyroangledt =(float)ti cycle_time gangleratedeg;
gangleraterads =(float)gangleratedeg * 0.017453;

/ DEGREESの新しい角度は、古い角度に最後のサイクル以降のジャイロからの角度の変化を加えたもので、新しい加速度の読み取り値が少し考慮されています/ angle =(float)((1-aa)*(angle + gyroangledt))+(aa * x_accdeg ); //主な角度計算関数*///角度を度からラジアンに変換

 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 <

void set_motor()

/ * leveli項は、OSMCに接続されているPWMモーター制御ポートに送信する準備ができている整数として-1023から+1023に再スケーリングされたレベル項です* / {

// if(level <-0.9)level = -0.9;//適切な制限内にあることを確認します//if(level> 0.9)level = 0.9;

int16_t leveli =(int16_t)(level * 1023); //ここで、「level」の浮動小数点値を取得し、それを1023で乗算してから整数にした後、値を「leveli」としてPWMジェネレーターにフィードします。

if(leveli <-1020)leveli =-1020; //(leveli> 1020)leveli = 1020;の場合、ボードから突然スローされたくないので、適切なPWM制限内にあることを再確認します。

/ポートB1にLEDまたはブザーを設定して、供給されるトルクが可能な最大値の50%を超える場合は、速度を落とすように警告します。この理由は、速度で前方に転倒し始めた場合に備えて、常に予備のモーター電力が必要になるためです。モーターはすでにフラットアウトで動作しているので、高速で転倒する可能性があります。自動チップバックルーチンを使用して、最高速度を自動的に制限するものもあります。今のところ私はこのように簡単にやります/

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

softstart =(float)softstart + 0.001; if(softstart> 1.0)softstart = 1.0;

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

OSMCが機能し、両方がOFFになってモーターがシャットダウンする/ *注:理由はわかりませんが、AHIとBHIを+12Vに配線するために最後に行った方向変更でモーターの切断を停止する//PinC1を設定してOSMCを無効にしない出力をゼロにすると、1はOSMC * / PORTC |=0x0cを無効にします。// C1をプルダウンして、OSMCの無効化を解除します。つまり、有効にします。PORTC&=〜0x02; //無効はオフですif(leveli <0){OCR1A = -leveli; // leveli変数は負の符号付きの値であるため、ALIはPWMで逆方向に進みます。ここでは、マイナス記号を保持してください。OCR1B = 0; // BLI = 0} else {OCR1A = 0; // leveli変数は正の符号付きの値であるため、ALI=0以降OCR1B=leveli; //BLIはPWMです}}

int main(void){InitPorts();

adc_init();

timer_init();

/ *初期傾斜開始コードボードを片側に傾けた状態でマイクロをオンにします。傾斜角度がゼロ(中間)ポイントバランスアルゴリズムを超えると、ライダーはマイクロをオンにします。それ以外の場合は、水平位置に傾斜するまでこのループに永久にロックされます。ライダーがボードに乗るとき*/tipstart = 0; accelraw = 0;

while(tipstart <1){

//これは、accsumの値を確認する前に、最初にマシンの電源を入れたときにSGフィルターが適切な安定した値になるようにするために必要です(以下)。

for(i = 0; i <20; i ++){
sample_inputs();
}

if(accsum <504 || accsum> 524){//
if(x_accdeg> 0){tipstart = 0; } else {tipstart = 1;
softstart = 0.4; }}

角度=0; cur_speed = 0; /*チルト開始コードの終わり。このポイントを超えると、マシンは水平になり、アクティブになります* /

sei();

while(1){sample_inputs();

set_motor();

}}

4

4 に答える 4

4

ビルドに間違ったMCUが指定されている可能性があります。DDRAはArduinoMegaのATmega1280に存在しますが、DDRAは通常のArduinoのATmega328には存在しません。

Arduino UIを使用している場合は、[ツール]|[ツール]に移動します。搭乗してArduinoMegaを選択します。

独自のビルドシステムを使用している場合は、gccコマンドラインで-mmcu=に指定した値を更新する必要があります。

于 2009-12-29T02:37:36.857 に答える
2

ここで締めくくりのコメントを省略したかもしれません。

/*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 >>>*/<<<
于 2009-12-29T01:40:46.523 に答える
0

コンパイラが「このスコープで宣言されていない」と言った場合、自分自身として次の質問をします。

どのスコープ宣言されましたか?

その質問に答えられない場合は、問題を発見したことになります。結局のところ、その名前が何を指しているのかわからない場合コンパイラーにどのように期待できますか?あなたはあなた書くどんなコードの専門家でもあることを忘れないでください。

物事がどのスコープで宣言されているかを判断できる場合、次のタスクは、そのスコープが使用しようとしているスコープとどのように関連しているかを判断することです。一般的な問題には、次のものがあります(ただしこれらに限定されません

  • 他の名前空間で宣言されました。::スコープ解決演算子を使用して、完全修飾名を付けます。
  • クラスのメンバーとして宣言されており、スタンドアロン関数で使用しようとしています。クラスのインスタンスを見つけて、そのオブジェクトを介して変数または関数にアクセスするか、クラスを変更して、新しい関数をそのメンバーの1つとして使用します。

宣言されたスコープが見つからない場合は、間違っている可能性のあることがいくつかあります。

  • スペルが間違っています。ドキュメントのスペルを確認し、コードを修正してください。
  • 含めるのを忘れたヘッダーで宣言されています。宣言されている場所を特定し、適切な#includeディレクティブを追加します。これはおそらくあなたの場合の問題です。
  • どこにも宣言されていません。どこで宣言すべきかを考え、そこで自分で宣言します。
于 2009-12-29T04:23:40.563 に答える
-1

これは、DIYセグウェイを制御するためのかなり単純なArduinoコードへのリンクです。

これはあなたのスケートボードのより良い出発点になると思います。

http://diysegway.blogspot.com/

幸運をお祈りしています

ジョン

于 2010-02-06T18:28:08.607 に答える