Domanda

Sto cercando di modificare questo codice nel tentativo di farlo funzionare su un Arduino Mega.Sono praticamente nuovo in C, quindi potrei aver commesso alcuni errori importanti.A proposito, questo è per uno skateboard autobilanciante.:P

Questo codice è preso da un ATmega32 (da :[url=http://sites.google.com/site/onewheeledselfbalancing/Home/twin-wheel-self-balancing-skateboard-lightweight-version/code4]http://sites.google.com/site/onewheeledsel...t- versione/codice4[/url] e sto cercando di farlo funzionare su un Arduino Mega.

Questo codice è stato scritto per una scheda di sviluppo ATmega32http://www.active-robots.com/products/controllr/m32db.shtml

Grazie!

Ecco il primo errore che riscontro:

Nella funzione 'void timer_init()':errore:«TCCR0» non è stato dichiarato in questo scopo Nella funzione 'int main()':

Qualcuno potrebbe spiegarmi cosa c'è che non va?Sono praticamente un principiante nella programmazione ma ho letto molti libri/siti web e sto imparando anche velocemente!^^ ed ecco il codice completo (la sua piuttosto lunga):

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

definire CLOCK_SPEED 16000000

definire OCR1_MAX 1023

typedef carattere senza segno u8;nullo set_motor_idle(void);nullo InitPorts(vuoto);livello galleggiante=0;galleggiante Pedale_acceleratore;galleggiante aa;galleggiante accelraw;float x_acc;somma mobile;float x_accdeg;

giroscopio galleggiante;

galleggiante gangleratoeg;galleggiante gangleraterad;galleggiante ti = 2,2;

guadagno complessivo fluttuante;controllo del guadagno flottante;volt batteria flottante = 24;galleggiante gyroangledt;angolo di galleggiamento;galleggiante anglerads;galleggiante equilibrio_coppia;galleggiante soft start;

float velocità_cur;float cycle_time = 0,0064;float Punto_equilibrio;float a0, a1, a2, a3, a4, a5, a6;//Variabili Savitzky-Golay per accelerometro

int io;intero j;int tipstart;nullo InnitPorts(vuoto) {PORTC=0x00;//Porto C pullup impostati su basso (nessuna uscita tensione) per iniziare con DDRC=0xFF;/I pin della porta C sono tutti impostati come uscita tramite il registro di direzione della porta C //PORTC |= (1<

DDRA=0x00;//all port A pin impostati come ingresso PORTA=0x00;//Porta di ingresso A pullule impostate a pullule basse

DDRD=0xFF;//Configura tutti i pin della porta D come output come prerequisito per OCR1A (PinD5) e OCR1B (Pin D4) funzionanti correttamente

PORTAB=0x00;//Porta B pullule impostate su bassa (nessuna tensione di uscita) per cominciare con DDRB=0xFF;//Tutti i pin della porta B impostati su output

} /* I/O:Sto usando ATMega32 16MHz con orologio esterno in cristallo.Nuovo disposizione pin pianificata al motore OSMC controller PC4 LED di bordo PD5/OC1A ALI -> Pin OSMC 6 PD4/OC1B BLI -> Pin OSMC 8 PC1 Disabilita -> Pin OSMC 4 PC2 BHI -> Pin OSMC 7 PC3 AHI -> Pin OSMC 5 PA6/ADC6 Vbatt/10 -> Pin OSMC 3 PA1/ADC1 giroscopio di frequenza di passo Accelerometro PA0/ADC0 / nulla adc_init(void) { / spegni comparatore analogico come noi non lo usiamo /ACSR = (1 <<ACD);/ selezionare PA0 /ADMUX=0;ADMUX |=(1< Imposta ADC prescaler a 128, abilitare l'ADC e avviare la conversione / ADCSRA = 0 | (1< / attendere la prima conversione fasulla finito */ while (ADCSRA & (1 << ADSC)) { } }

uint16_t adc_read(uint8_t canale) {
/* seleziona il canale / ADMUX = canale;ADMUX |=(1< avvia conversione /
ADCSRA |= (1 <<ADSC);/
attendere fino a conversione completata / mentre (ADCSRA & (1 << ADSC)) { } / restituisci il risultato */ restituito ADCW;}

/* 156 cicli al secondo, 6,4 ms per ciclo MISURATO SU OSCILLOSCOPIO*/ /* leggi tutto gli ingressi ADC e fare qualche conversione */ void sample_inputs(void) {

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

= (virgola mobile) adc0;per (j=0;j<7;j ) { adc1 = adc_read(1);//giroscopio PA1 giroscopio = (float) giroscopio adc1;//utilizzando una media di 7 campioni per ciclo per il gyro in modo da ottiene un aggiornamento completo con ogni ciclo del programma }

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

posizione PA2*/ adc3 = adc_read(3);/* Posizione leva tirata indietro posizione PA3*/ adc4 = adc_read(4);/* Posizione del pedale PA4*/ adc5 = adc_read(5);/* Leva di posizione spinta posizione in avanti PA5*/ //adc6 = adc_read(6);/* Input Vbatt da OSMC (attualmente non utilizzata) posizione PA6*/ //Sav filtro Golay solo per accel a0 = a1;a1 = a2;a2 = a3;a3 = a4;a4 = a5;a5 = a6;a6 = (float) acceleraw;accsum = (float) ((-2*a0) (3*a1) (6*a2) (7*a3) (6*a4) (3*a5) (-2*a6))/21;//Salva Calcolo di Golay

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

// lisci eventuali picchi di tensione e dà intervallo 0-3 Pedale_acceleratore=(float) Pedale_acceleratore*0,9 0,1*adc4/341;// lisci eventuali picchi di tensione e dà intervallo 0-3

/Cancella il motore se il morto il pulsante viene lasciato andare //(controllo del guadagno anche la variabile cablata attraverso questo pulsante adc2 if (adc2<100) { Acceleratore_pedale=0,001;controllo guadagno=0,001;} overallgain = gaincontrol*softstart;//cosa fare se la leva tirata indietro o spinta in avanti o non facendo qualsiasi cosa:Punto_equilibrio = 514;if (adc3>100) Punto_equilibrio=534;

if (adc5>100) Punto_equilibrio=494;

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

misurare il tempo del loop con un oscilloscopio

/Elaborazione del segnale dell'ACCELEROMETRO/ /Sottrarre gli offset/ x_acc=(float) accsum - punto_di equilibrio;//accsum è il valore di SG per accelerometro, non una vera "somma" così non c'è bisogno di dividere per 7 se (x_acc<-250) x_acc=-250;//cap accelera i valori fino ad un intervallo compreso tra -250 e 250 (inclinazione di 80 gradi in ogni direzione) se (x_acc>250) x_acc=250;/* La variazione dell'angolo dell'accelerometro è di circa 3,45 unità per grado di inclinazione in gamma 0-30 gradi(senza theta) Convertire inclinazione a gradi di inclinazione da sensore dell'accelerometro.Senza angolo approssimativamente = angolo per piccoli angoli così Non c'è bisogno di fare trigonometria.x_acc sotto è ora in GRADI*/

x_accdeg= (float) x_acc/-3.45;//Il segno meno corregge un dorso al montaggio dell'accelerometro anteriore!

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

cioè.il mio punto zero richiesto sarà quella lettura meno 512*/

/Cambio di angolo giroscopico di 20mV per grado al secondo da datasheet dà il cambiamento di 4.096 unità (su una scala da 0 a 1023) per grado al secondo cambiamento dell'angolo limita la velocità di cambio del giroscopio angolo a poco inferiore al massimo tasso è effettivamente in grado di misurazione (100°/sec).Nota tutti questi le frazioni sono arrotondate al numero intero più tardi, poco prima di essere inviato al Generatore PWM che a sua volta è collegato al controllore del motore/ gangleratedeg=(float)((girosum/7) - 508)/4,096;//gyrosum è una somma di un gruppo di 7 campioni, quindi dividere per 7 per valore del giroscopio se (gangleratedeg < -92) gangleratedeg=-92;se (gangleratedeg

92) gangleratedeg=92 /Accendo e spento la porta B2 una volta per programma principale ciclo in modo da poter collegare un oscilloscopio ad esso ed elaborare il ciclo del programma tempo Io uso il tempo di ciclo per lavorare fuori cambio di angolo giroscopico per ciclo in cui si devono conoscere la durata di questo tempo intervallo/PORTA &= (0<

/ti rappresenta il ridimensionamento per la "i" o fattore integrale (attualmente 2.2 qui) gyroangledt è anglechange dall'ultimo CICLO in gradi da gyro sensore, dove ti è il fattore di scala (dovrebbe teoricamente essere circa 1 ma 2,2 rende il bordo sentire più stretto)
ganglerate è ora in unità di gradi al secondo aa varia il tempo costante, vale a dire più piccolo valore aa rende tempo costante dell'accelerometro più lungo come corregge lentamente per il giroscopio deriva
/

aa=0,005;giroangolo = (galleggiante)titempo di ciclogangleratoeg;
gangleraterads=(float)gangleratedeg*0.017453;

/il nuovo angolo in GRADI è il vecchio angolo più cambiamento di angolo dal giroscopio dal ultimo ciclo con poco di nuovo lettura accelerata fattorizzata in/ angolo = (float)((1-aa) * (angolo giroangolot)) (aa * x_accdeg);//la funzione di calcolo dell'angolo principale*/ //Convert angolo da gradi a radianti

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

+ (0,5*radi di frequenza gangle);

cur_speed = (float)(cur_speed (Pedale_acceleratore * bilanciamento_coppia * cycle_time)) * 0,999;

/*Il valore del livello va da -1 a 1 e rappresenta il ciclo di funzionamento da inviare al motore.Conversione in radianti ci aiuta a rimanere entro questi limiti livello = (balance_coppia cur_speed) * in generale;

}

void timer_init() { TCCR0 = 0 | (1<

// La modalità PWM è "PWM, fase corretta", 10 bit" TCCR1A = 0 | (1<

(1<

void set_motore()

/* Il termine leveli è il termine level ridimensionato da -1023 a 1023 come intero pronto per l'invio al motore PWM porte di controllo che sono a loro volta collegato all'OSMC*/ {

//se (livello<-0,9) livello= -0,9;//verifica che siamo entro limiti ragionevoli //se (livello>0,9) livello=0,9;

int16_t livelloi = (int16_t)(livello*1023);//NOTA qui noi prendere il valore in virgola mobile che abbiamo finito con per "livello", moltiplichiamo esso da 1023 e poi trasformarlo in un integer prima di immettere il valore in il generatore PWM come "leveli"

se (livello<-1020) leveli=-1020;//doppio controllo siamo entro limiti PWM ragionevoli, in quanto non di essere improvvisamente sbalzati fuori dal scheda se (livello>1020) livello=1020;

/Impostare il LED o il cicalino sulla porta B1 a avvertimi di rallentare se la coppia di torsione deve essere consegnato è superiore al 50% del max possibile La ragione di questo è che hai sempre bisogno di un motore di riserva potenza nel caso in cui si avvia ribaltamento avanti a velocità Se il motore già esecuzione flat-out si sarebbe in procinto di cadere ad alta velocità!Alcuni usano un auto-tip indietro di routine per automaticamente limite della velocità massima.Per ora lo farò. in questo modo come più facile/

if (livello<-0,7 || livello>0,7) {
PORTB |= (1< PORTB &= (0<

softstart = (flottante) softstart+0.001;se (softstart>1.0) softstart=1.0;

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

OSMC al lavoro ed entrambi a OFF per chiudere motore spento /*NOTA:Non so perché, ma a arresto del motore di taglio sulla direzione cambiamenti che ho avuto alla fine di hard wire AHI e BHI a 12V / / Non disabilitato OSMC impostando l'uscita PinC1 a zero, a 1 disabilita l'OSMC*/ PORTC |= 0x0c;//rendere C1 tirato giù così un-disabilita l'OSMC i.e.lo abilita.PORTAC &= ~0x02;//la disattivazione è disattivata se (livello<0) { OCR1A = -leveli;// ALI è PWM andando all'indietro come variabile leveli è un valore firmato negativo, mantenere il Meno firma qui!OCR1B = 0;// BLI = 0 } altro { OCR1A = 0;// ALI = 0 in avanti come livelloi variabile è un valore firmato positivo OCR1B = livelloi;// BLI è PWM } }

int main(vuoto) { InitPorts();

adc_init();

timer_init();

/* Codice iniziale tilt-start Attiva micro mentre bordo inclinato su un lato, pilota in procinto di fare un passo su di esso, se inclinazione l'angolo attraversa il bilanciamento del punto zero (medio) algoritmo diventa operativo altrimenti bloccato in questo loop per sempre fino a quando non viene inclinato in posizione livellata man mano che il pilota sale a bordo*/ tipstart=0;acceleraw = 0;

mentre (tipstart<1){

// è necessario per consentire l'SG filtro per avvolgere fino alla corretta stalla valore alla prima accensione della macchina, prima di esaminare il valore di accsum (sotto).

per (i=0;io<20;i++) {
campione_input();
}

if (accusum<504 || accsum>524) { //
if (x_accdeg>0) { tipstart=0;} else { tipstart=1;
avvio graduale=0,4;} }

angolo=0;velocità_cur=0;/* fine dell'inclinazione codice di avvio.Se si va oltre questo punto poi la macchina è diventata livello ed è attivo*/

sei();

while (1) { sample_inputs();

set_motore();

} }

È stato utile?

Soluzione

Molto probabilmente hai specificato l'MCU sbagliato per la tua build.Mentre DDRA esiste sull'ATmega1280 di un Arduino Mega, DDRA non esiste sull'ATmega328 di un normale Arduino.

Se stai usando l'interfaccia utente di Arduino, vai su Strumenti | Scheda e scegli Arduino Mega.

Se stai utilizzando il tuo sistema di compilazione, dovrai aggiornare il valore specificato per -mmcu= sulla riga di comando di gcc.

Altri suggerimenti

Penso che potresti aver lasciato un commento di chiusura qui:

/*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 >>>*/<<<

Quando il compilatore ti dice che qualcosa "non è stato dichiarato in questo ambito", poniti questa domanda:

Che portata era è dichiarato?

Se non puoi rispondere a questa domanda, allora hai scoperto il problema.Dopotutto, se Voi non sai a cosa si riferisce quel nome, come puoi aspettarti che lo faccia il compilatore?Ricordati che Voi sono l'esperto di qualsiasi codice Voi scrivere.

Se tu Potere determinare in quale ambito è dichiarato l'oggetto, quindi il compito successivo è determinare in che modo tale ambito si collega all'ambito in cui si sta tentando di utilizzarlo.I problemi tipici includono (ma non sono limitati a) quanto segue:

  • È stato dichiarato in qualche altro spazio dei nomi.Usa il :: operatore di risoluzione dell'ambito per fornire un nome completo.
  • È stato dichiarato come membro di una classe e stai tentando di utilizzarlo in una funzione autonoma.Trova un'istanza della classe e accedi alla variabile o alla funzione tramite quell'oggetto oppure modifica la classe per avere la tua nuova funzione come uno dei suoi membri.

Se tu non posso trova in quale ambito è stato dichiarato, ci sono alcune cose che potrebbero essere errate:

  • Hai scritto male.Controlla l'ortografia nella documentazione e correggi il codice.
  • È dichiarato in qualche intestazione che hai dimenticato di includere.Scopri dove è dichiarato e aggiungi l'appropriato #include direttiva. Probabilmente è questo il problema che fa al caso tuo.
  • Non è dichiarato da nessuna parte.Scopri dove si trova Dovrebbe essere dichiarato e dichiararlo lì tu stesso.

Ecco un collegamento al codice Arduino ragionevolmente semplice per il controllo di un Segway fai-da-te.

Penso che questo sarebbe un punto di partenza migliore per il tuo skateboard.

http://diysegway.blogspot.com/

Auguri

John

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top