Pergunta

Eu estou tentando modificar esse código em uma tentativa de fazê-lo funcionar em um Arduino Mega.Sou muito nova para C assim, eu posso ter feito alguns erros graves.A propósito, esta é para uma auto balanceamento de skate.:P

Este código é obtido a partir de um ATmega32 (a partir de :[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] e eu estou tentando fazê-lo funcionar em um Arduino Mega.

Este código foi escrito para um ATmega32 developpement conselho http://www.active-robots.com/products/controllr/m32db.shtml

Obrigado!

Aqui está o primeiro erro que encontrar :

Em função de 'void timer_init()':erro:'TCCR0' não foi declarado na este escopo Em que a função 'int main()':

Alguém poderia me explicar o que está errado?Eu sou praticamente um iniciante em programação, mas eu li um monte de livros/site e estou aprendendo rápido demais!^^ e aqui está o código completo (sua muito longa):

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

definir CLOCK_SPEED 16000000

definir OCR1_MAX 1023

typedef unsigned char u8;vazio set_motor_idle(void);vazio InitPorts(void);de nível de flutuador=0;float Throttle_pedal;float aa;float accelraw;float x_acc;float accsum;float x_accdeg;

float gyrosum;

float gangleratedeg;float gangleraterads;float ti = 2.2;

float overallgain;float gaincontrol;float batteryvolts = 24;float gyroangledt;float ângulo;float anglerads;float balance_torque;float softstart;

float cur_speed;float cycle_time = 0.0064;float Balance_point;float a0, a1, a2, a3, a4, a5, a6;//Savitzky-Golay variáveis para acelerômetro

int i;int j;int tipstart;vazio InitPorts(void) { PORTC=0x00;//Porta C pullups definido para baixa (sem saída de tensão) para começar DDRC=0xFF;//Porta C pinos de todo definida como a saída por meio de a porta C direção registrar //PORTC |= (1<

DDRA=0x00;//todas as portas de Um conjunto de pinos como entrada de PORTA=0x00;//Porta de entrada pullups baixa pullups

DDRD=0xFF;//Configurar a porta de todos os pinos D como saída, como pré-requisito para OCR1A (PinD5) e OCR1B Pin (D4) de trabalho corretamente

PORTB=0x00;//Porta B pullups definido para baixa (sem tensão de saída) para começar DDRB=0xFF;//Todos os pinos da porta B para definir saída

} /* E / s:Eu estou usando ATMega32 16MHz externo com relógio de cristal.Novo planejado pinos para OSMC motor controlador PC4 a Bordo LED PD5/OC1A ALI -> OSMC pino 6 PD4/OC1B BLI -> OSMC pino 8 PC1 Disable -> OSMC pino 4 PC2 BHI -> OSMC pino 7 PC3 AHI -> OSMC pino 5 PA6/ADC6 Vbatt/10 -> OSMC pino 3 PA1/ADC1 campo giroscópio PA0/ADC0 acelerômetro / void adc_init(void) { / desligue analógico comparador de como nós não usá-lo / ACSR = (1 << ACD);/ selecione PA0 / ADMUX = 0;ADMUX |=(1< Conjunto de ADC prescaler 128, habilitar a ADC, e iniciar a conversão / ADCSRA = 0 | (1< / aguarde até que o falso primeira conversão terminar */ while (ADCSRA & (1 << ADSC)) { } }

uint16_t adc_read(uint8_t canal) {
/* selecione o canal / ADMUX = canal;ADMUX |=(1< iniciar a conversão /
ADCSRA |= (1 << ADSC);/
aguarde até que a conversão terminar / enquanto (ADCSRA & (1 << ADSC)) { } / o retorno resultado */ return ADCW;}

/* 156 ciclos por segundo, 6.4 ms por ciclo MEDIDO NO OSCILOSCÓPIO*/ /* ler todos o ADC entradas e fazer a conversão de algumas */ 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);//gyro pin PA1 gyrosum = (float) gyrosum + adc1;//com uma média de 7 amostras por loop para o gyro por isso fica um atualização completa com cada ciclo do programa }

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

posição PA2*/ adc3 = adc_read(3);/* Posição da alavanca puxada para trás posição PA3*/ adc4 = adc_read(4);/* Throttle_pedal posição AP4*/ adc5 = adc_read(5);/* Posição da alavanca empurrado encaminha posição AP5*/ //adc6 = adc_read(6);/* Vbatt entrada da OSMC (não utilizado atualmente) posição PA6*/ //Sav Golay filtro para accel apenas 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;//Sav Golay cálculo

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

//suaviza qualquer picos de tensão e dá faixa de 0-3 Throttle_pedal=(float) Throttle_pedal*0.9 + 0.1*adc4/341;//suaviza qualquer picos de tensão e dá faixa de 0-3

//Corta o motor se o dead mans o botão é deixar de ir //(gaincontrol variável também com fio por meio do botão para adc2 se (adc2<100) { Throttle_pedal=0.001;gaincontrol=0.001;} overallgain = gaincontrol*softstart;//o que fazer se a alavanca puxada de volta ou avança ou não fazer qualquer coisa:Balance_point = 514;se (adc3>100) Balance_point=534;

se (adc5>100) Balance_point=494;

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

medir o tempo de loop com um osciloscópio

/ACELERÔMETRO de processamento de sinal/ /Subtrair deslocamentos/ x_acc=(float) accsum - Balance_point;//accsum é SG valor para acelerômetro, não é um verdadeiro "soma" de modo não há necessidade de dividir por 7 se (x_acc<-250) x_acc=-250;//tampa de aceleração valores para um intervalo de -250 a +250 (80 graus de inclinação em cada sentido) se (x_acc>250) x_acc=250;/* Acelerômetro para mudar o ângulo é de cerca de 3.45 unidades por grau de inclinação em intervalo de 0 a 30 graus(pecado theta) Converter de inclinação em graus de inclinação de sensor do acelerómetro.O pecado ângulo cerca de = ângulo para ângulos pequenos, de modo não há necessidade de fazer trigonometria.x_acc abaixo está agora em GRAUS*/

x_accdeg= (float) x_acc/-3.45;//O sinal de menos corrige para uma volta a frente de montagem do acelerômetro!

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

i.e.meu ponto zero será que a leitura menos 512*/

/Giroscópio de mudar o ângulo de 20mV por graus por seg a partir de folha de dados dá-alteração de 4.096 (unidades na escala de 0 a 1023) por grau por segundo, ângulo de alterar Este limita a taxa de variação do giroscópio ângulo um pouco menos que o máximo a taxa é realmente capaz de de medição (100deg/seg).Nota: todos estes as frações são arredondadas para um inteiro mais tarde, pouco antes de ela ser enviada para o Gerador de PWM, que por sua vez é ligado ao controlador do motor/ gangleratedeg=(float)((gyrosum/7) - 508)/4.096;//gyrosum é uma soma de um grupo de 7 amostras, assim, dividir por 7 para giroscópio de valor se (gangleratedeg <-92) gangleratedeg=-92;se (gangleratedeg

92) gangleratedeg=92 /Eu viro a porta B2 e fora de uma vez por programa principal ciclo para que eu possa anexar um osciloscópio para ele, trabalhar o ciclo de programa tempo eu uso o ciclo de tempo para trabalhar fora giroscópio de mudar o ângulo por ciclo, onde você precisa saber o tamanho de este tempo intervalo de/ PORTB &= (0<

/ti representa o dimensionamento para o "eu" ou integral fator (atualmente 2.2 aqui) gyroangledt é anglechange desde o último CICLO, em graus, a partir giroscópio sensor, onde ti é fator de escala (deve, em teoria, ser de cerca de 1, mas 2.2 torna conselho sentir mais apertado)
ganglerate está agora em unidades de graus por segundo aa varia o tempo constante, eu.e de menor valor, faz com que aa acelerômetro constante de tempo mais longo como lentamente ele corrige para o giroscópio drift
/

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

/novo ângulo, em GRAUS, é velho ângulo além de alteração no ângulo de giro desde último ciclo com pouco de novo aceleração de leitura levadas em conta/ angle = (float)((1-aa) * (ângulo de+gyroangledt)) + (aa * x_accdeg);//o principal ângulo de cálculo da função*/ //Converter ângulo de graus para radianos

 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;

/*O valor é de -1 a +1 e representa o ciclo de trabalho a ser enviado para o motor.Converter para radianos ajuda-nos a permanecer dentro destes limites nível = (balance_torque + cur_speed) * overallgain;

}

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

// Modo PWM é "PWM, a Fase Correta, 10-bit" TCCR1A = 0 | (1<

(1<

void set_motor()

/* O leveli termos é o nível prazo redimensionado a partir de 1023 para +1023 como um inteiro pronto para enviar para o PWM motor portas de controle que por sua vez são ligado a OSMC*/ {

//se (nível<-0.9)=nível -0.9;//verifica se estamos dentro dos limites sensíveis //if (nível>0.9) nível=0.9;

int16_t leveli = (int16_t)(nível*1023);//NOTA aqui nós tomar o valor de ponto flutuante temos acabou com o "nível de", devemos multiplicar por 1023 e, em seguida, torná-lo em uma inteiro antes de alimentar o valor em o gerador de PWM como "leveli"

se (leveli<-1020) leveli=-1020;//verifica somos dentro sensível PWM de limites, como não quero, de repente, ser jogado para fora do conselho se (leveli>1020) leveli=1020;

/Conjunto de LED ou campainha na Porta B1 a avisar-me para abrandar se o torque a ser entregue mais do que 50% de max. possível razão para isso é que você sempre precisa de alguma reserva motora de energia no caso de você começar a gorjeta para a frente em velocidade Se o motor já a execução de televisão-você estaria prestes a cair em alta velocidade!Alguns usam um auto-sugestão de volta a rotina automaticamente limite de velocidade máxima.Por agora vou fazê-lo desta forma, como mais fácil/

se (nível<-0.7 | nível | >0.7) {
PORTB |= (1< PORTB &= (0<

softstart = (float) 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 para o trabalho e tanto OFF (desligado) para desligar motor para baixo /*NOTA:Não sei por que, mas parada do motor de corte para fora em direção as alterações que eu tinha no final de fio duro AHI e BHI para +12V / / Onu-desactivado OSMC por definição PinC1 saída para zero, 1 desative a OSMC*/ PORTC |= 0x0c;//faça C1 puxado para baixo para onu-desativa a OSMC i.e.permite-lo.PORTC &= ~0x02;//desactivar está fora de se (leveli<0) { OCR1A = -leveli;// ALI está PWM indo para trás, como leveli variável é negativo assinado valor, a manter o sinal de subtração aqui!OCR1B = 0;// BLI = 0 } else { OCR1A = 0;// ALI = 0 vai para a frente como leveli a variável é um sinal positivo de valor OCR1B = leveli;// BLI é PWM } }

int main(void) { InitPorts();

adc_init();

timer_init();

/* Inicial tilt-código de início de Ligar micro enquanto conselho pender para um lado, piloto sobre a etapa em que, se a inclinação ângulo de cruzamentos de zero (meio) ponto de equilíbrio algoritmo torna-se operacional caso contrário, preso neste ciclo para sempre até que ele é cotado para a posição de nível como o piloto fica no tabuleiro*/ tipstart=0;accelraw = 0;

enquanto (tipstart<1){

// você precisa esta opção para permitir que o SG filtro de vento até a adequada estável valor quando pela primeira vez máquina, antes de olhar para o valor da accsum (abaixo).

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

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

ângulo=0;cur_speed=0;/* fim do tilt código de início.Se ir além deste ponto em seguida, a máquina tornou-se nível e é ativo*/

sei();

while (1) { sample_inputs();

set_motor();

} }

Foi útil?

Solução

Provavelmente você tem errado MCU especificado para a sua construção.Enquanto DDRA existe no ATmega1280 em um Arduino Mega, DDRA não existe no ATmega328 regular Arduino.

Se você estiver usando o Arduino INTERFACE de usuário, vá para Ferramentas | Conselho de administração e escolha o Arduino Mega.

Se você estiver usando o seu próprio sistema de compilação, você precisará atualizar o valor que você especificar para -mmcu= no gcc linha de comando.

Outras dicas

Eu acho que você pode ter deixado um fechamento comentário aqui:

/*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 o compilador diz que algo "não foi declarado neste âmbito," como a si mesmo esta pergunta:

O âmbito foi é declarada?

Se você não pode responder a essa pergunta, então você já descobriu o problema.Afinal, se você não sabe o que esse nome se refere, como você pode esperar que o compilador?Lembre-se de que você é o especialista em qualquer código você escrever.

Se você pode determinar o escopo da coisa que for declarado e, em seguida, a próxima tarefa é determinar como esse escopo se refere ao âmbito de aplicação que você está tentando usá-lo.Problemas típicos incluem (mas não estão limitados a) o seguinte:

  • Ele foi declarado em algum outro espaço de nomes.Use o :: escopo do operador de resolução de dar um nome totalmente qualificado.
  • Ele foi declarado como um membro de uma classe e que você está tentando usá-lo em uma função autônomo.Quer encontrar uma instância da classe e acessar a variável ou função de objeto, ou alterar a classe para ter sua nova função como um de seus membros.

Se você não pode encontrar escopo que foi declarado, em seguida, há algumas coisas que podem estar erradas:

  • Você escreveu errado.Verificar a ortografia na documentação e corrigir o seu código.
  • Ele é declarado no cabeçalho que você esqueceu de incluir.Descobrir onde é declarado e adicione o adequado #include directiva. Este é, provavelmente, o problema no seu caso.
  • Não declaradas em qualquer lugar.Descobrir onde é que deve ser declarado e declará-lo lá mesmo.

Aqui está um link para razoavelmente simples código do Arduino para controle de um DIY Segway.

Este seria um ponto de partida melhor para o seu skate, eu acho.

http://diysegway.blogspot.com/

Melhores cumprimentos,

João

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top