Страница 1 из 1

Условия сравнения со сложными функциями не работают...

Добавлено: Ср май 01, 2013 23:28:20
andrikll
Вопрос в заголовке. привожу текст целиком.. наверно так будет проще. В общем устройство.. Двигатель постоянного тока, на нем стоит оптический энкодер который долго настраивал но запустил. есть еще 2 регулятора... хотел одним регулятором (энкондер механика) крутить этот мотор а вторым (резистор через АЦП) регулировать положение мотора по прямолинейной функции. До этого дело не дошло. Когда я сравниваю просто положение мотора и энкодера, все супер, но стоит сделать что либо сложное и мотор начинает выполнять не предсказуемые перемещения при регулировании. (Определение функций портов сокращу....)

Chip type : ATmega48
Clock frequency : 1,000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/

#include <mega48.h>

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here

}

#define ADC_VREF_TYPE 0x60

// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}

unsigned int reg=3000, mot=2500, cifra;
unsigned char display=1, pause, new_reg, old_reg, new_mot, old_mot, gas, b, a, shim, mot_reg;

// Declare your global variables here

void segment1(void)
{ PORTB.7=0;
PORTB.5=0;
PORTB.4=0;
PORTB.6=1;
if (cifra1==0) PORTD=0x88;
if (cifra1==1) PORTD=0xeb;
if (cifra1==2) PORTD=0x91;
if (cifra1==3) PORTD=0xc1;
if (cifra1==4) PORTD=0xe2;
if (cifra1==5) PORTD=0xc4;
if (cifra1==6) PORTD=0x84;
if (cifra1==7) PORTD=0xe9;
if (cifra1==8) PORTD=0x80;
if (cifra1==9) PORTD=0xc0;
}

void segment2(void)
{
PORTB.6=0;
PORTB.5=0;
PORTB.4=0;
PORTB.7=1;
if (cifra2==0) PORTD=0x88;
if (cifra2==1) PORTD=0xeb;
if (cifra2==2) PORTD=0x91;
if (cifra2==3) PORTD=0xc1;
if (cifra2==4) PORTD=0xe2;
if (cifra2==5) PORTD=0xc4;
if (cifra2==6) PORTD=0x84;
if (cifra2==7) PORTD=0xe9;
if (cifra2==8) PORTD=0x80;
if (cifra2==9) PORTD=0xc0;
}

void segment3(void)
{ PORTB.7=0;
PORTB.6=0;
PORTB.5=0;
PORTB.4=1;
if (cifra3==0) PORTD=0x88;
if (cifra3==1) PORTD=0xeb;
if (cifra3==2) PORTD=0x91;
if (cifra3==3) PORTD=0xc1;
if (cifra3==4) PORTD=0xe2;
if (cifra3==5) PORTD=0xc4;
if (cifra3==6) PORTD=0x84;
if (cifra3==7) PORTD=0xe9;
if (cifra3==8) PORTD=0x80;
if (cifra3==9) PORTD=0xc0;
}
void segment4(void)
{ PORTB.7=0;
PORTB.6=0;
PORTB.4=0;
PORTB.5=1;
if (cifra4==0) PORTD=0x88;
if (cifra4==1) PORTD=0xeb;
if (cifra4==2) PORTD=0x91;
if (cifra4==3) PORTD=0xc1;
if (cifra4==4) PORTD=0xe2;
if (cifra4==5) PORTD=0xc4;
if (cifra4==6) PORTD=0x84;
if (cifra4==7) PORTD=0xe9;
if (cifra4==8) PORTD=0x80;
if (cifra4==9) PORTD=0xc0;
}

void regul (void)
{
if (old_reg==0) {if(new_reg == 3) reg++; if(new_reg == 1) reg--; }
if (old_reg==1) {if(new_reg == 0) reg++; if(new_reg == 3) reg--; }
if (old_reg==3) {if(new_reg == 1) reg++; if(new_reg == 0) reg--; }
if (old_reg>3) display++;

}

void motor (void)
{
if (old_mot==1) {if (new_mot == 3) mot=mot+1;};
if (old_mot==3) {if (new_mot == 1) mot=mot-1;};
}


void motor_drive (void)
{

pause++;

if (mot_reg>20) shim=40; else shim=5;
if (pause>=255-shim) a=1; else a=0;
if (pause<=shim) b=1; else b=0;
if (mot > reg+10) mot_reg=mot-reg, PORTB.3=0, PORTB.2|=a;
if (mot < reg-3) mot_reg=reg-mot, PORTB.2=0, PORTB.3|=b;
if ((mot <= reg+10) && (mot >= reg-3)) PORTB.2=0, PORTB.3=0;

}

void main(void)
{

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTB=0x00;
DDRB=0xFD;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization// Clock source: System Clock// Clock value: 125,000 kHz
// Mode: Normal top=FFh// OC0A output: Disconnected// OC0B output: Disconnected
TCCR0A=0x00; TCCR0B=0x02; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization// ADC Clock frequency: 7,813 kHz// ADC Voltage Reference: AVCC pin// ADC Auto Trigger Source: Free Running
// Only the 8 most significant bits of// the AD conversion result are used// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On// ADC4: On, ADC5: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA7;
ADCSRB&=0xF8;

// Global enable interrupts
#asm("sei")

while (1)
{
new_reg = 4*!PINB.1+2*!PINC.1+!PINC.0;
if (old_reg!=new_reg) regul();
old_reg=new_reg;

gas = read_adc(2);

if (display==4) display=1;
if (display==2) cifra=(reg-reg%10)/10;
if (display==1) cifra=(mot-mot%10)/10;
if (display==3) cifra=gas;

cifra1=cifra%10; // Описываем выбор значений для сегментов цифр 1
segment1() ; // переход в функцию сегмент для засветки сегмента 1

cifra2=(cifra%100-cifra%10)/10;
segment2() ;
new_mot = 2*PINC.5+PINC.4; //Obnovlenie znacheniya new_mot, obrabotka znacheniya povorota motora,
if (old_mot!=new_mot) motor();
old_mot=new_mot; // сброс значения олд_мот
motor_drive(); //obrabotka podachi signala na motor

cifra3=(cifra%1000-cifra%100)/100;
segment3() ;
cifra4=(cifra%10000-cifra%1000)/1000;
segment4() ;

}; //Для while

}

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Ср май 01, 2013 23:52:46
andrikll
Функция motor_drive.
Еще одна заметка если быстро крутить энкодер то двигатель может поменять направление вращения, при этом значения точно не выходят за диапазон (смотрю на экране).

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 09:17:14
uk8amk
Все условия работают, когда правильно написаны...

Энкодер как я понял квадратурный?
Не пробовали его обработку вытащить из главного цикла в прерывание? Туда же управление моторами.

И еще во это:
andrikll писал(а):Clock frequency : 1,000000 MHz
маловато может быть.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 13:53:44
andrikll
Прерывания не пробовал но хотел бы! не знаю что значит квадратурный.. если вы про регулятор то механика (как в магнитоллах на громкости).. если вы про энкодер мотора то оптический из мыши. Простое условие работает когда я напрямую сравниваю мот и рег... мотор крутит пока не получит значение рег.. как только ставлю что то посложнее..рег+гас уже начинает глючить. а если что либо с перемножением то атас!

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 14:27:46
ChipKiller
andrikll - по-хорошему лучше все переписать. Писать все "в лоб" не стоит. например вместо

Код: Выделить всё

void segment1(void)
{ PORTB.7=0;
PORTB.5=0;
PORTB.4=0;
PORTB.6=1;
if (cifra1==0) PORTD=0x88;
if (cifra1==1) PORTD=0xeb;
if (cifra1==2) PORTD=0x91;
if (cifra1==3) PORTD=0xc1;
if (cifra1==4) PORTD=0xe2;
if (cifra1==5) PORTD=0xc4;
if (cifra1==6) PORTD=0x84;
if (cifra1==7) PORTD=0xe9;
if (cifra1==8) PORTD=0x80;
if (cifra1==9) PORTD=0xc0;
}
... и прочих segment_x

Код: Выделить всё

flash char table[10]=0x88,0xeb,0x91,0xc1,0xe2,0xc4,0x84,0xe9,0x80,0xc0;
....
PORTD=table[cifra];
... и делается это в обработчике прерывания по переполнению таймера, например.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 14:56:16
andrikll
ChipKiller Спасибо огромное.. делал через свич.. фигня полная.. не знаю почему.. все засвечено остается. Мне нужен пример по прерываниям.. я сам не напишу.. пересмотрел много чего, как окнкретно использовать не понял до конца...
По таймеру тоже ничего не получается... Читал читал.. чтобы флаг ТОВ не сбрасывался, прерывания нужно отключить и вручную сбрасывать.. но никакими способами не получилось это использовать.

Стараюсь писать сам даже если смотрю на примеры.. по крайней мере так я знаю что к чему в программе. даташит по таймерам прочел и на русском и на английском. могу кинуть что я писал по таймерам..
То uk8amk
Поставил бы больше, но без кварца.. боюсь залочить.. пока все получается не дышу на схему...Использую пока с простым условием мот== рег и все работает. Вопрос именно почему если применить сложное уравнение или переменную являющуюся произведением и суммой других (фанк=рег*10+гэс и иф мот==фанк) то начинает "глючить"

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 15:08:05
mulder790
выложи файлом, (и если можно мне пришли проектом, я посмотрю и пришлю переработанную версию)
по поводу вывода согласен лучше в прерывании, или по if или по case.
это пример (прошу не пинать сильно писал по памяти)

Код: Выделить всё

flash char table[10]=0x88,0xeb,0x91,0xc1,0xe2,0xc4,0x84,0xe9,0x80,0xc0;
//массив обображения цифр на сегментном индикаторе
static unsigned int figure=0; //переменная номера отображаемого сегмента
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
if(figure=>3)figure=0; //цикл выбора цифры для обображения
else figure++;

	switch(figure)  //цикл с выводом информации на сегменты
	{
		case 0:
			segment1();
		break;
		case 1:
			segment2();
		break;
		case 2:
			segment3();
		break;
		case 3:
			segment4();
		break;
		
		}

}

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 19:24:00
uk8amk
andrikll писал(а):почему если применить сложное уравнение или переменную являющуюся произведением и суммой других (фанк=рег*10+гэс и иф мот==фанк) то начинает "глючить"
Есть вероятность, что оптимизатор компилятора считает ваш код бредом и выбрасывает лишнее/перетасовывает инструкции. По крайней мере WinAVR или Keil при уровне выше -O0 так и поступают во многих случаях. CVAVR версий 1.хх имел не слишком продвинутый оптимизатор и почти ничего не выбрасывал. В любом случае вам следует предоставлять более формальные доказательсва в виде листинга, а не русскоязычного варианта (фанк=рег*10+гэс и иф мот==фанк) . И с указанием что конкретно глючит. Иначе мы ничем не поможем.
andrikll писал(а):По таймеру тоже ничего не получается... Читал читал.. чтобы флаг ТОВ не сбрасывался, прерывания нужно отключить и вручную сбрасывать.. но никакими способами не получилось это использовать.
Эмм, он(флаг) сам вобще-то сбрасывается вы выходу из прерывания.
• Bit 0 – TOV2: Timer/Counter2 Overflow Flag
The TOV2 bit is set (one) when an overflow occurs in Timer/Counter2. TOV2 is cleared
by hardware when executing the corresponding interrupt handling vector. Alternatively,
TOV2 is cleared by writing a logic one to the flag.
Тоесть можно и так и так.
Вообще CVAVR(а как я понял в нем вся работа идет) имеет очень дружелюбные мастеры кода.
А потренироваться можно на симуляторе AVR Studio или в Proteus-е. Это если аппаратного отладчика совсем нету.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 20:17:09
andrikll
что такое уровень -О0? (минус О ноль?) и как этого избежать? хотелось бы оперировать сложными математическими зависимостями в будущем! Ладно я трениться на железке... может кто то еще подкинеть что либо....Спасибо! появились мысли-идеи......
uk8amk условие по переполнению таймера, если я не использую прерывания, не происходит.. не пойму почему. К сожалению имею плохую привычку переписывать все в одной и той же проге... и не сохранил код в котором это вышло...

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 20:53:36
ChipKiller
andrikll писал(а):хотелось бы оперировать сложными математическими зависимостями в будущем!
.. не нужно забывать, что 8-ми битный AVR - это не Pentium. Поэтому, где только можно "сложных математических зависимостей" нужно избегать, так же как использования типа float.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Чт май 02, 2013 22:42:25
andrikll
Это понятно.. никто уравнений третьего порядка не вставляет.. флоат тоже не нужен.. хватет того что есть. (инт, чар)
я так понимаю figure можно и чаром сделать и не статиком? с первой ошибкой не знаю что.. не разу не пользовал...

Разобрался.. ошибки устранил.. шью. Проверяю идеи по перемножениям.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Пт май 03, 2013 12:32:08
ChipKiller
andrikll писал(а):не знаю почему.. все засвечено остается. Мне нужен пример по прерываниям.. я сам не напишу.. пересмотрел много чего, как окнкретно использовать не понял до конца...
как пример подойдет скачать

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Пт май 03, 2013 16:59:49
mulder790
Выложи весь проект так проще будет, и легче ошибки найти просто я пишу больше под gcc-avr.

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Пт май 03, 2013 17:12:44
ChipKiller
mulder790 писал(а):Выложи весь проект...
так там весь проект и есть ... единственное - он под CV AVR, но библиотеки не используются, так что переделать под gcc-avr не сложно...

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Пт май 03, 2013 17:46:56
mulder790
ChipKiller писал(а):
mulder790 писал(а):Выложи весь проект...
так там весь проект и есть ... единственное - он под CV AVR, но библиотеки не используются, так что переделать под gcc-avr не сложно...
я конечно понимаю что почти весь (благо пишу в обоих компиляторах).
просто что бы помочь и отладить проект проще его просто подгрузить как файл) хотя каждый делает так как ему удобнее)))

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Пт май 03, 2013 18:02:56
ChipKiller
mulder790 писал(а):я конечно понимаю что почти весь
... а я не понимаю почему почти весь?
Изображение

Re: Условия сравнения со сложными функциями не работают...

Добавлено: Вс май 05, 2013 16:30:39
andrikll
Спасибо огромное! Всё заработало.. Вобщем очень внимательно нужно смотреть (как бы мысли вслух) на тип данных с которыми оперируешь по "математике" и поменьше перемножений.. прерывания работают, экран на "свитче" отлично заработал.