Вопрос

Я пытаюсь изменить этот код, пытаясь заставить его работать на мега Arduino. Я в значительной степени новичок в C, так что, возможно, я допустил несколько серьезных ошибок. Кстати, это для скейтборда для самостоятельного уравновешивания. :П

Этот код взят из Atmega32 (от: [url =http://sites.google.com/site/onewheeledselfbalancing/home/twin-wheel-skalancing-skateboard-lightweight-version/code4§ версия/code4 [/url И я пытаюсь заставить его работать на мега -ардуино.

Этот код был написан для совета по разработке ATMEGA32http://www.active-robots.com/products/controllr/m32db.shtml

Благодарю вас!

Вот первая ошибка, с которой я сталкиваюсь:

В функции 'void timer_init ()': error: 'tccr0' не был объявлен в этой области в функции 'int main ()':

Может ли кто -нибудь объяснить мне, что случилось? Я в значительной степени новичок в программировании, но я читал много книг/веб -сайта, и я тоже учусь быстро! ^^ И вот полный код (он довольно длинный):

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

Определите clock_speed 16000000

Определите OCR1_MAX 1023

Typedef unsigned char U8; void set_motor_idle (void); void initports (void); уровень плавания = 0; float throttle_pedal; Плавать аа; Float Accelraw; float x_acc; Float Accsum; float x_accdeg;

поплавок гиросом;

float gangleratedeg; Float Gangleraterds; float ti = 2,2;

float overgegain; Float Gaincontrol; Float Batteryvolts = 24; Float Gyrooangledt; Угол плавания; Поплавок Англерад; 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 для акселерометра

int i; int j; int tipstart; void initports (void) {portc = 0x00; // подтягивание порта C, установленные на низкий (без выходного напряжения) для начала с ddrc = 0xff; // Порт C Pins все установлено в виде вывода через регистр направления порта C // portc | = (1

Ddra = 0x00; // Весь порт A -контакты устанавливают как входные порта = 0x00; // порты входные подтягивания установлены на низкие подтягивания

Ddrd = 0xff; // Настройка всех контактов порта D в качестве вывода в качестве обязательного условия для OCR1A (PIND5) и OCR1B (PIN D4) работаю надлежащим образом

Portb = 0x00; // подтягивание порта B, установленные на низкий (без выходного напряжения) для начала с ddrb = 0xff; // все контакты порта B, установленные для вывода

} /* IO: я использую Atmega32 16 МГц с внешними кристаллическими часами. Новое запланированное расположение штифтов для контроллера двигателя OSMC PC4 встроенного светодиода PD5/OC1A ALI -> PIN 5 PD4/OC1B BLI -> PIN OSMC 8 PC1 DISABLE -> PIN 5 PC2 BHI -> PIN 7 PC3 AHI -> PIN 5 OSMC 5 PC2 BHI -> PIN 7 PC3 AHI -> OSMC PIN 5 PA6/ADC6 VBATT/10 -> PIN 3 PA1/ADC1 Гиро скорости PA0/ADC0 Акселерометр / void adc_init (void) { / Отключите аналоговый компаратор, так как мы его не используем / Acsr = (1 << acd); / Выберите PA0 / Admux = 0; Admx | = (1 <Set ADC Prescaler в 128, включить ADC и начало преобразования / Adcsra = 0 | (1 < / Подождите, пока не закончится поддельная первая конверсия */ while (adcsra & (1 << adsc)) {}}

uint16_t adc_read (uint8_t канал) {
/* Выберите канал / Admux = канал; Admx | = (1 <Start Conversion /
Adcsra | = (1 << adsc); /
Подождите, пока не закончится преобразование / while (adcsra & (1 << adsc)) {} / вернуть результат */ return adcw; }

/* 156 циклов за секунду, 6,4 мс на цикл, измеренный при осциллографе*//* Считайте все входы АЦП и сделайте некоторое преобразование*/ 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); // гирозовый штифт 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); /* DELOTTLE_PEDAL POLICE PA4*/ ADC5 = ADC_READ (5); /* Рычаг положения выдвинул позицию вперед pa5*/// adc6 = adc_read (6); /* Вход VBATT из OSMC (не используется в настоящее время) PA6*/// SAV GOLAY FILTER для ускорения только 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 Расчет

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

// сглаживает любые всплески напряжения и дает диапазон 0-3 дроссельная заслонка_печол = (float) throttle_pedal*0,9 + 0,1*ADC4/341; // сглаживает любые шипы напряжения и дает диапазон 0-3

// разрезает двигатель, если кнопка Dead Mans отпускается // (переменная GainControl также проведена через эту кнопку к ADC2 IF (ADC2 <100) {throttle_pedal = 0,001; GainControl = 0,001;} ablegain = Gaintontrol*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

Измерить время петли с осциллографом

/Обработка сигнала акселерометра/ /Вычтите смещения/ x_acc = (float) accsum - balance_point; // accsum-это значение SG для акселерометра, а не истинная «сумма», поэтому не нужно делиться на 7 if (x_acc <-250) x_acc = -250; // Cap Accel значения в диапазоне от -250 до +250 (наклон 80 градусов в каждую сторону) if (x_acc> 250) x_acc = 250; /* Изменение угла угла акселерометра составляет около 3,45 единиц на наклон на градус в диапазоне 0-30 градусов (грех) преобразование наклона до градусов наклона из датчика акселерометра. Угол греха приблизительно = угол для маленьких углов, поэтому не нужно делать тригонометрию. x_acc ниже сейчас в градусах*/

x_accdeg = (float) x_acc/-3,45; // Знак минус исправляет для монтажа с задней к передним акселерометра!

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

то есть моя необходимая нулевая точка будет, что чтение минус 512*/

/Уголов гироскопии на угол на 20 мВ на градус в секунду от таблицы данных дает изменение 4,096 единиц (по шкале от 0 до 1023) на градус на градус на угол изменение, это ограничивает скорость изменения угла гироса, что на самом деле меньше, чем максимальная скорость. Способен измерять (100Deg/Sec). Обратите внимание, что все эти фракции собраны до целого числа позже, прежде чем его отправит в генератор ШИМ, который, в свою очередь, подключен к контроллеру двигателя/gangleratedeg = (float) ((Gyrosum/7) - 508) /4.096; // Гиросом представляет собой сумму группы из 7 образцов, поэтому делится на 7 для гироскопии, если (Gangleratedeg <-92) Gangleratedeg = -92; if (Gangleratedeg

92) Gangleratedeg = 92 /Я включаю и выключаю порт B2 один раз на один основной программный цикл, чтобы прикрепить к нему осциллограф и выработать время цикла программы, я использую время цикла для работы по поводу изменения угла гиропа интервал/ Portb & = (0

/Ti представляет масштабирование для гидроэнгунта «I» или интегрального фактора (в настоящее время 2,2 здесь) является англояжным знаком с последнего цикла в градусах от гироскопического датчика, где Ti является масштабирующим фактором (теоретически должно быть около 1, но 2,2 заставляет доску чувствовать себя крепче)
Ganglerate в настоящее время находится в единицах градусов в секунду AA изменяет постоянную времени, то есть меньшее значение AA делает акселерометр постоянным дольше, поскольку он медленно корректирует для дрейфа гироса
/

aa = 0,005; gyroangledt = (float) tiвремя циклаGangleratedeg;
Gangleraterds = (float) Gangleratedeg*0,017453;

/Новый угол в градусах - это старый угол плюс изменение угла от гиропа/ angle = (float) ((1-aa) * (angel + gyroangledt)) + (aa * x_accdeg); // Функция расчета основного угла*/// преобразовать угол из градусов в радиан

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

+ (0,5*ганглератерад);

cur_speed = (float) (cur_speed + (throttle_pedal * balance_torque * cycle_time)) * 0,999;

/*Значение уровня составляет от -1 до +1 и представляет рабочий цикл, который должен быть отправлен в двигатель. Преобразование в радианы помогает нам оставаться в пределах этих пределов = (balance_torque + cur_speed) * overgain;

}

void timer_init () {tccr0 = 0 | (1

// ШИМ-режим-«ШИМ, ФАЗА ПРАВИЛЬНО, 10-битный» TCCR1A = 0 | (1

(1<

void set_motor ()

/* Условия уровня -это уровень, снятый с -1023 на +1023 в качестве целого числа, готовых отправлять в порты управления двигателем ШИМ, которые в свою очередь подключены к OSMC*/ {

// if (level <-0,9) level = -0,9; // проверяет, что мы находимся в разумных пределах // if (уровень> 0,9) Уровень = 0,9;

int16_t leveli = (int16_t) (уровень*1023); // ПРИМЕЧАНИЕ ЗДЕСЬ. Мы принимаем значение с плавающей запятой, с которой мы получили для «уровня», мы умножаем его на 1023, а затем превращаем его в целое число, прежде чем подавать значение в генератор ШИМ как «leveli»

Если (leveli <-1020) leveli = -1020; // Двойные проверки мы находимся в пределах разумных ограничений ШИМ, как не хотим внезапно быть выброшенным с платы, если (leveli> 1020) leveli = 1020;

/Настроить светодиод или зуммер на порту B1, чтобы предупредить меня о замедлении, если крутящий момент будет доставлен, составляет более 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 для работы и обоих, чтобы выключить мотор вниз /*Примечание: не уверен, почему остановить вырезание двигателя при изменениях направления, которые у меня были в конце концов, на твердый провод AHI и BHI до +12 В / / / / UN-DISADED OSMC. Настройка вывода PINC1 на ноль, A 1 отключил бы OSMC*/ portc | = 0x0c; // Сделать C1 стянуть так, чтобы он не давал, так как OSMC IE позволяет это. Portc & = ~ 0x02; // Отключить выключен if (leveli <0) {ocr1a = -leveli; // Али - это ШИМ, идущий назад, так как переменная уровня является отрицательным значением, подписав ЗДЕСЬ! Ocr1b = 0; // bli = 0} else {ocr1a = 0; // ali = 0, продвигаясь вперед как переменная уровня, является положительным значением ocr1b = leveli; // bli is pwm}}

int main (void) {initports ();

adc_init ();

timer_init ();

/* Первоначальный код наклона наклона включите Micro, в то время как плата с одной стороны на одну сторону, всадник, который собирается встать на него, если угол наклона пересекает нулевой (средний) алгоритм баланса точек, в противном случае заблокирован в этом цикле, пока он не будет нанесен до уровня положения. как гонщик попадает на доску*/ tipstart = 0; accelraw = 0;

while (tipstart <1) {

// Вам нужно, чтобы это позволило фильтру SG доходить до надлежащего стабильного значения, когда вы сначала включаете машину, прежде чем смотреть на значение accsum (ниже).

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 ();

} }

Это было полезно?

Решение

Скорее всего, у вас неправильный MCU, указанный для вашей сборки. В то время как DDRA существует на ATMEGA1280 на мега -Arduino, DDRA не существует на ATMEGA328 обычного Arduino.

Если вы используете пользовательский интерфейс Arduino, перейдите в инструменты | Прата и выберите Arduino Mega.

Если вы используете свою собственную систему сборки, вам нужно обновить значение, которое вы указываете для -MMCU = в командной строке GCC.

Другие советы

Я думаю, что вы, возможно, оставили здесь заключительный комментарий:

/*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 для контроля над Segway.

Это было бы лучшей отправной точкой для вашего скейтборда, я думаю.

http://diysegway.blogspot.com/

С наилучшими пожеланиями

Джон

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top