PrimussTh

Мастерская и лаборатория => Я не волшебник, я только учусь... => Тема начата: slav0n от 15 Апрель 2011, 15:09:00

Название: Исходники, алгоритмы.
Отправлено: slav0n от 15 Апрель 2011, 15:09:00
Выкладываем здесь различные примеры исходников.

Для начала очень компактное целочисленное вычисление квадратного корня.
unsigned short isqrt(unsigned long x)
{
     unsigned short y = 0;
     unsigned long  z = 1;
     while(x >= z)
    {
         x -= z;
         z += 2;
         y++;
    };
    return y;
}
Название: Программный ведомый шины I2C на ассемблере
Отправлено: slav0n от 15 Апрель 2011, 15:55:32
Программная реализация ведомого шины I2C.
Так как делалось для конкретной задачи эмуляции LNBP21, реализована простейшая отработка только двух байтов: байт адреса и управляющий байт. Для полноценной реализации протокола I2C требуется доработка. Разобравшимся в исходнике, думаю, это будет несложно.
;Эмулятор шины I2C LNBP21
;Отрабатывает вкл-выкл питания конвертера PINB.3
;а также переключение поляризации PINB.4

.include "tn13def.inc" ;ATtiny13

;Hfuse FF
;Lfuse 7A

.def data      = r23
.def count_bit = r24
.def count_byte= r25

.equ SCL = 1     ;опрделяем пины
.equ SDA = 0     ;шины I2C

.equ ON_OFF = 3   ;определяем выходные
.equ H_V    = 4   ;пины

.equ DEVICE =$10 ;определяем адрес устройства

;***** BEGIN *****
ldi data,(1<<ON_OFF)|(1<<H_V)
out DDRB,data  ;конфигурируем порт на выход

WAIT_START:
ldi count_byte,2

WAIT_SCL:
sbis PINB,SCL  ;ждем когда клок будет 1
rjmp PC-1

sbis PINB,SDA  ;ждем когда data будет 1
rjmp PC-1

sbic PINB,SDA  ;ждем когда data будет 0
rjmp PC-1

sbis PINB,SCL  ;если клок не 1,
rjmp WAIT_SCL  ;это не START, идем ждать клок 1

sbic PINB,SCL  ;ждем когда клок будет 0
rjmp PC-1

;=======принимаем байт ===================
LOOP_st:
ldi count_bit, 8

LOOP:
sbis PINB,SCL  ;ждем когда клок будет 1, при этом ведущий устанавливает бит для передачи
rjmp PC-1

lsl data       ;сдвигаем регистр data на один разряд влево
sbic PINB,SDA  ;проверяем линию данных
ori  data,1    ;если единица, пишем её в data

sbic PINB,SCL  ;ждем когда клок будет 0
rjmp PC-1

dec count_bit   ;уменьшаем счетчик разрядов на 1
brne LOOP      

dec count_byte  ;уменьшаем счетчик байтов на 1
brne ADR       ;если это был 1-й байт, идем на проверку адреса

;-------устанавливаем выходные сигналы-------------
;-------в зависимости от второго принятого байта---
out PORTB,count_bit  ;обнуляем выходы

sbrs data, 3
sbi PORTB,H_V

sbrc data, 2
sbi PORTB,ON_OFF

rjmp ACK
;-----------------------------------------

ADR:
cpi  data,DEVICE ;если адрес не наш, выходим на ожидание условия START
brne WAIT_START

ACK:
sbi DDRB, SDA  ;порт на вывод
cbi PORTB,SDA  ;выводим ноль на SDA, тоесть отвечаем АСК

sbis PINB,SCL  ;ждем когда клок будет 1
rjmp PC-1

sbic PINB,SCL  ;ждем когда клок будет 0,при этом ведущий читает наш АСК
rjmp PC-1

cbi DDRB,SDA   ;порт на ввод - отпускаем СДА

tst count_byte  ;проверяем счетчик принятых байт
brne LOOP_st   ;если не 0, идем принимать второй байт

rjmp WAIT_START
Название: Вычисление синус, косинус и арктангенс. CORDIC
Отправлено: slav0n от 15 Апрель 2011, 18:43:43
Еще один достойный внимания алгоритм.
/*
Алгоритм CORDIC ([CO]ordinate [R]otation [DI]gital [C]alculation)

Позволяет быстро и компактно вычислять синус, косинус и арктангенс
без использования плавающей точки.
Данные в функцию передаются и возвращаются
с помощью структуры типа codr_data

аргументы и результаты умножаются и делятся на 100 соответственно.
*/

/*=========================
синус-косинус
-------------------------
начальные условия:
mod= 0
angle= угол, y=0, x= 6073

результат:
y = sin
x = cos

=========================
арктангенс
-------------------------
начальные условия:
mod= 1
angle= 0, y = y, x = x

результат:
angle = -atan(y/x)
==========================*/


#define  K 16468
#define  KK 6073 // (1/16468)

const int tab_arctg[13] PROGMEM =
    {4500,2657,1404,713,358,179,90,45,22,11,6,3,1,};

struct codr_data{
int angle;
int y;
int x;
char mod;
};

void CORDIC(struct codr_data *cd)
{                    
int y_next;
int x_next;
int arctg;
int *p = tab_arctg;

for(u8 i=0;i<13;i++)
{
arctg = pgm_read_word(p++);

x_next = cd->x >> i;
y_next = cd->y >> i;

if(cd->mod == 0) //sin cos
{
if(cd->angle < 0)
{
x_next = -x_next;
y_next = -y_next;
}
else arctg = -arctg;
}
else
if(cd->mod == 1) //arctg
{
if(cd->y < 0)
{
x_next = -x_next;
y_next = -y_next;
arctg = -arctg;
}
}

cd->y -= x_next;
cd->x += y_next;

cd->angle += arctg;
}
}
/************ пример использования *********************/
void main(void)
{
struct codr_data cd;
int my_cos, my_sin, my_atan, coord_x, coord_y, my_angl;

cd.mod = 0; //sin cos
cd.angle = my_angl;
cd.y = 0;
cd.x = 6073;

CORDIC(&cd);

my_cos = cd.x;
my_sin = cd.y;


cd.mod = 1; //atan
cd.angle = 0;
cd.y = coord_y;
cd.x = coord_x;

CORDIC(&cd);

my_angl = cd.angle;
}
Название: Изменяем параметр двумя кнопками
Отправлено: slav0n от 01 Июль 2011, 07:23:00
Изменяем двумя кнопками некое значение по кругу от 0 до limit-1 с шагом step. Направление счета изменяем знаком step.
Операторы сравнения не используются.

void Up_Down_button(unsigned char *value, unsigned char limit, signed char step)
{
*value += limit;

if(Button_Down)*value +=step;
      else
if(Button_Up  )*value -=step;

*value %= limit;
}
Название:
Отправлено: lizard66 от 27 Октябрь 2011, 22:43:06
Всю тригонометрию делал методом степенных рядов Тейлора-Маклонена, поэтому арккосинус был уже на 90% готов, а корень делал по этому алгоритму:

x1 = 1;
x2 = 0;
while (true) {
  x2 = (x1+N/x1)/2;
  if (fabs(x1-x2) < eps) break;
  x1 = x2;
}

для точности два знака после запятой достаточно 4-5 итераций
Название: Re: ПО для Primuss3-spectrum
Отправлено: slav0n от 27 Октябрь 2011, 23:53:41
Цитата: "lizard66"
а корень делал по этому алгоритму
Цитата: "lizard66"
Сорри, все пишем на асме
:-):
Название:
Отправлено: lizard66 от 28 Октябрь 2011, 08:22:12
Цитата: "slav0n"
Цитата: "lizard66"
а корень делал по этому алгоритму
Цитата: "lizard66"
Сорри, все пишем на асме
:-):

Алгоритм так наглядней выглядет или на асме тебе былоб понятней? Сорри за синтаксис, "С" владею плохо, мот надо было переменные обьявить и функции?  :-):
Название: Re: Исходники , алгоритмы.
Отправлено: slav0n от 28 Октябрь 2011, 09:41:37
Цитата: "lizard66"
Алгоритм так наглядней выглядет или на асме тебе былоб понятней? Сорри за синтаксис, "С" владею плохо
Не думаю, что на асме алгоритмы выглядят понятней чем на C. Почти машинный язык, однако.  :-):
Твой способ на "человеческом" языке выглядит примерно так:
unsigned sqrt_cpu_newton(long L)
{
unsigned rslt = (unsigned)L;
long div = L;
if (L <= 0) return 0;
while (l)
{
div = (L / div + div) / 2;
if (rslt > div) rslt = (unsigned)div;
   else return rslt;
}
}
взято отсюда (http://algolist.manual.ru/maths/count_fast/intsqrt.php)
Название:
Отправлено: lizard66 от 28 Октябрь 2011, 09:47:00
Цитата: "slav0n"
взято отсюда (http://algolist.manual.ru/maths/count_fast/intsqrt.php)

Очень познавательная ссылка, спасибо.
Название: скользящий сглаживающий алгоритм
Отправлено: slav0n от 13 Декабрь 2011, 06:04:27
Нашел на хабре (http://habrahabr.ru/blogs/algorithm/134375/) интересную формулу

output = alpha*input + (1-alpha)*output[i-1]
0<=alpha<=1

Применительно к микроконтроллерам можно  использовать так:

output = input /2 + output[i-1] /2
Название:
Отправлено: slav0n от 20 Январь 2012, 18:17:57
Вот здесь (http://iprog.pp.ru/forum/read.php?f=1&i=29902&t=29897#reply_29902) нашел до кучи еще один вариант сглаживания:

output = output[i-1] + (input - output[i-1])*alpha
0<alpha<1

Цитировать
> Научите какой алгоритм (формулу) требуется установить в контроллер
> для реализации инерционного звена 1-го порядка...

Обозначим X - вход звена, Y - выход звена.

Формула для вычисления выхода инерционного звена 1-го порядка (на языке ST):
Y := Y + (X-Y)*K;

Где K - коэффициент, который обычно вычисляется заранее (один раз) по формуле:
K:=T/(t+T);
Где
t - постоянная времени инерционного звена,
T - период расчета (если расчет выполняется в каждом скане контроллера, то берется время скана; если по прерыванию - то тик прерывания и т.д. )

K имеет смысл в пределах от 0 до 1 (не включая границ). При K=0 выход звена "замораживается" (т.е. постоянная времени звена равна бесконечности), при K=1 звено превращается в повторитель (т.е. постоянная времени звена равна нулю).

>..., интегратора
> (здесь вроде все
> понятно),
> реального дифференциала...

Требуется дополнительная переменная X0 для хранения значения входа из предыдущего скана. Расчет:
Y := (X-X0)*K;
X0 := X;

Где K - коэффициент, который обычно вычисляется заранее (один раз) по формуле:
K:=t/T;
Где
t - постоянная времени дифференцирующего звена,
T - период расчета (если расчет выполняется в каждом скане контроллера, то берется время скана; если по прерыванию - то тик прерывания и т.д.)

> ..., скользящего среднего?

Поскольку Виктор Бардичев уже ответил, добавлю только, что реализация скользящего среднего (СС) в контроллере требует работы с массивами и индексной или косвенной адресацией. Преимущества СС по сравнению с инерционным звеном (экспоненциальным фильтром) неочевидны, поэтому на практике я никогда не сталкивался с необходимостью реализовать именно СС.
Название: Алгоритмические симфонии из одной строки кода - как и почему
Отправлено: slav0n от 21 Март 2012, 07:54:54
Любопытный способ получения мелодий.
http://countercomplex.blogspot.com/2011 ... ne-of.html (http://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from-one-line-of.html" target="_blank)
http://countercomplex.blogspot.com/2011 ... music.html (http://countercomplex.blogspot.com/2011/10/some-deep-analysis-of-one-line-music.html" target="_blank)

А здесь можно самому поиграться - http://wurstcaptures.untergrund.net/music/ (http://wurstcaptures.untergrund.net/music/" target="_blank)
Название:
Отправлено: slav0n от 22 Март 2012, 15:38:16
Попробовал реализовать этот алгоритм на AVR. Код на Си получается простой до безобразия.  :-):
Для этого используем аппаратный 8-битный таймер в режиме Fast PWM.


Вот собственно код для ATtiny13
#include <avr/io.h>

main(void)
{
TCCR0B=(0<<CS02)|(0<<CS01)|(1<<CS00); // clk
TCCR0A=(1<<COM0A1)|(0<<COM0A0)| //pinout 1-0-1
(1<<WGM01)|(1<<WGM00); //Fast PWM

DDRB = (1<<PB0); //sound out Timer/Counter0

long t;

for(;;t++)
{
//  Немного формул взятых из Интернета. Желаемое раскомментировать.
                // OCR0A = t * ((t>>12|t>>8)&63&t>>4);
// OCR0A = (t>>7|t|t>>6)*10+4*(t&t>>13|t>>6);
// OCR0A = t*(42&t>>10);
// OCR0A = t*((42&t>>10)%14);
// OCR0A = (t*3)&t>>8;
// OCR0A = t*9&t>>4|t*5&t>>7|t*3&t/1024;
// OCR0A = t>>4|t&((t>>5)/(t>>7-(t>>15)&-t>>7-(t>>15)));
// OCR0A = t>>6&1?t>>5:-t>>4;
// OCR0A = t&t%255;
// OCR0A = (t>>6|t|t>>(t>>16))*10+((t>>11)&7);
// OCR0A = ((t*(t>>8|t>>9)&46&t>>8))^(t&t>>13|t>>6);
// OCR0A = (t*5&t>>7)|(t*3&t>>10);
// OCR0A = t*(((t>>9)&10)|((t>>11)&24)^((t>>10)&15&(t>>15)));
// OCR0A = t*(((t>>9)^((t>>9)-1)^1)%13);
// OCR0A = (t>>5)|(t>>4)|((t%42)*(t>>4)|(0x15483113)-(t>>4))/(t>>16)^(t|(t>>4));
// OCR0A = t>>6^t&37|t+(t^t>>11)-t*((t%24?2:6)&t>>11)^t<<1&(t&598?t>>4:t>>10);

// OCR0A = ((t&4096)?((t*(t^t%255)|(t>>4))>>1):(t>>3)|((t&8192)?t<<2:t));
// OCR0A = t*(t>>((t&4096)?((t*t)/4096):(t/4096)))|(t<<(t/256))|(t>>4);
// OCR0A = ((t%42)*(t>>4)|(0x15483113)-(t>>4))/(t>>16)^(t|(t>>4));

// OCR0A = (((((t*((t>>9|t>>13)&15))&255/15)*9)%(1<<7))<<2)%6<<4;

// OCR0A = ((t>>5&t)-(t>>5)+(t>>5&t))+(t*((t>>14)&14));
OCR0A = (t*(t>>12)*64+(t>>1)*(t>>10)*(t>>11)*48)>>(((t>>16)|(t>>17))&1);

// OCR0A = t*t/(t>>12&t>>8)<<7;
// OCR0A = 8*t*t*(t>>(t>>10)%3+15)/(3+(t>>10&(t>>15&3|4)))|t/16;

char d = 200; // переменной d подбираем темп мелодии
while(--d)asm("nop"::);
}
}
Название: Re: Исходники , алгоритмы.
Отправлено: Azumi от 23 Март 2012, 14:59:58
slav0n, для привязки дисплея к примусу, Вы использовали самодельную библиотеку? Не поделитесь версиеи для кодвижна?
А то мне понравилось такое расположение ножек, чтоб все не на одном порту висело, а на разных, произвольно.
Название: Re: Исходники , алгоритмы.
Отправлено: slav0n от 23 Март 2012, 15:26:23
Цитата: "Azumi"
для привязки дисплея к примусу, Вы использовали самодельную библиотеку? Не поделитесь версиеи для кодвижна?
Для какого конкретно дисплея, символьного или графического? Да,и я пишу в WinAvr. Синтаксис немного отличается от кодвижена.
Название: Re: Исходники , алгоритмы.
Отправлено: Azumi от 23 Март 2012, 15:45:50
Прошу прощения, забыл уточнить) Для символьного.
А библиотека подоидет от винавр к кодвижну?
Что-то все фанатеют по винавр и примеров в сети для него больше... Неужели он и правда лучше, или это просто дело привычки? Как-то раз пробовал, так мне оно показалось слишком усложненным.
Название:
Отправлено: slav0n от 23 Март 2012, 17:55:48
В общем-то библиотеки как таковой нет. Надо еще подумать - как представить то что написано в удобоваримом виде.  :-)
А пока вот нашел - готовая библиотека AVR-GCC LCD library – mixed pin support (http://winavr.scienceprog.com/avr-gcc-lcd-library-%E2%80%93-mixed-pin-support)
Название: Re: Исходники , алгоритмы.
Отправлено: Azumi от 23 Март 2012, 19:00:42
Завтра на работе попробую, спасибо.
А сделать так, чтоб RW (пятую ногу), можно было повесить на землю - это сложно?
Вообще, планируется написать прошивку, чтобы проверить уже готовыи примус, но без карты. + попутно разобраться с дисплеем)

Я просто дисплеи недавно получил, специально для сборки примуса, а до этого не писал под них. Пытаюсь понять, что к чему)

Пока еще не разобрался, как вписывать свои знаки в свободные ячеики памяти, и как ножки в произвольные порты подключать.
Также, непонятно, зачем нужен 8 битныи режим, если 4 битныи прекрасно работает (я вообще далек от программирования, потому для меня это не очевидно).
Название: WinAVR подключение LCD HD44780
Отправлено: slav0n от 24 Март 2012, 09:14:40
Вот немного кода. Можно настроить на любые ноги МК.
RW на корпус, 4-битный режим.
//===== определяем порты подключенные к индикатору ========
#define set_RS  PORTD |= (1<< 5)
#define clr_RS  PORTD &=~(1<< 5)

#define set_E   PORTD |= (1<< 4)
#define clr_E   PORTD &=~(1<< 4)

#define set_D4  PORTD |= (1<< 0)
#define clr_D4  PORTD &=~(1<< 0)

#define set_D5  PORTD |= (1<< 1)
#define clr_D5  PORTD &=~(1<< 1)

#define set_D6  PORTD |= (1<< 7)
#define clr_D6  PORTD &=~(1<< 7)

#define set_D7  PORTD |= (1<< 6)
#define clr_D7  PORTD &=~(1<< 6)

 #define COM  0
 #define DAT  -1

 
 // =================== запись тетрады ======================
void Write4bit(char tetr)
{
set_E;                   // устанавливаем бит Е

if(tetr & 0x01) set_D4;
else clr_D4;
if(tetr & 0x02) set_D5;
else clr_D5;
if(tetr & 0x04) set_D6;
else clr_D6;
if(tetr & 0x08) set_D7;
else clr_D7;

clr_E;                // сбрасываем бит Е
_delay_us(25);                      
}

 // ====================запись команд/данных===============
void WriteComDat(char byte_wr, char rs)
{
if(rs== COM)clr_RS;     // rs=0 - команды
else set_RS;     // иначе rs=1 - данные

Write4bit(byte_wr>>4);  // записываем старшую тетраду          
Write4bit(byte_wr);     // записываем младшую тетраду
_delay_us(100);         // ждем 100 микросекунд

if(rs==COM) _delay_ms(1);  // если была команда, то ждем еще 1 милисекунду
}

 // ================= инициализация индикатора ============================
void InitLcd(void)    
{
// массив данных инициализации ЖКИ-индикатора
const char byte_init[]={0x10,0x10,0x10,0x02,0x01,0x14,0x0C,0x2c};

for(unsigned char i=0;i<8;i++) WriteComDat(byte_init[i], COM);
}

//=================== очистка экрана ====================================
 void ClrScr(void)
{
WriteComDat(1,COM);
_delay_ms(5); // ждем 5 милисекунд
}

// ================== инициализация области CGRAM ========================
void InitCGram(unsigned char *buf)
{
WriteComDat(0x40, COM); // установка видео-адреса в области CGRAM
for(unsigned char i=0;i<64;i++) WriteComDat(*buf++, DAT); // загрузка символов в CGRAM
}

//=================== печать символа =====================================
void PrintSymbol(unsigned char symbol,unsigned char Position)
{
WriteComDat(Position|0x80, COM); // установка видео-адреса
WriteComDat(symbol, DAT);          // передача символа
}

Название: Re: Исходники, алгоритмы.
Отправлено: AlekseiKO от 18 Апрель 2016, 03:48:10
Мужики не знал где написать, вот решил тут! Так что не пинайте за вопрос. Я не профи, просто любитель.
Вопрос не относится к примусу!
Значит так:
Есть мега 8, есть прошивка в hex , схема....
Короче собрал все в кучу, спаял, прошил мегу , выставил фьзы как требовалось.
Программа запустилась на меге.
3 кнопки. 1 меню, 2 +, 3 -
В меню выбираю значение "частоту" и начинаю ее повышать или уменьшать. Но при нажатии на кнопку значение прыгает через 1 и даже больше. (Пример: 20, 23, 25, 27, 30)
И если быстро быстро, резко резко , нажать на кнопку то только тогда как положено на 1 деление переключается.

Так вот вопрос. Время нажатия на кнопку чем определятся ? В коде программы? Или же номиналами деталей какими то?

Спасибо
Название:
Отправлено: lizard66 от 18 Апрель 2016, 08:24:17
Цитата: "AlekseiKO"
В меню выбираю значение "частоту" и начинаю ее повышать или уменьшать. Но при нажатии на кнопку значение прыгает через 1 и даже больше. (Пример: 20, 23, 25, 27, 30)
И если быстро быстро, резко резко , нажать на кнопку то только тогда как положено на 1 деление переключается.

Так вот вопрос. Время нажатия на кнопку чем определятся ? В коде программы? Или же номиналами деталей какими то?

Спасибо
С дребезгом можно бороться как программно, так и аппаратно, чаще программно. В данном случае его побороли плохо, либо кнопки убитые.
Схему покажите.
Название:
Отправлено: AlekseiKO от 18 Апрель 2016, 12:23:17
Кнопки вроде нормальные. пробывал ставить другую. так же было.
схемку накидал почти от руки,на скоряк. За исключение некоторых мелочей стандартных.
Название:
Отправлено: slav0n от 18 Апрель 2016, 13:12:12
Самое простое, если писатель прошивки не забыл включить встроенные в мегу подтягивающие резисторы, то внешние на 1к можно вообще убрать, а параллельно кнопкам поставить конденсаторы. Если же внутренние подтяжки не задействованы, то внешние надо поставить на 20-50к, чтобы не завышать емкость сглаживающих кондеров. Эту емкость подобрать экспериментально, начиная примерно от 0.01мкФ.
Название: Re: Исходники, алгоритмы.
Отправлено: lizard66 от 18 Апрель 2016, 14:56:05
Ну, аппаратным антидребезгом тут не пахнет, а на PORTC автор мог и АЦП с медлинным тактом задействовать в качестве борьбы с дребезгом. Тут либо с софтом копаться, либо на каждую кнопку по Шмидту или RS-триггеру и кнопки с трехконтактные (с перемыканием), либо как Славка рекомендует емкости подобрать
Название:
Отправлено: slav0n от 18 Апрель 2016, 16:34:35
Цитата: "lizard66"
а на PORTC автор мог и АЦП с медлинным тактом задействовать в качестве борьбы с дребезгом.
обычно делаем счетчик итераций главного цикла.
При нажатии на кнопку счетчик запускается, при отпускании - сбрасывается.
В зависимости от содержимого счетчика решаем что делать.
Например код на сях
while(1)
{
if(btn_prs)//проверяем кнопку
{
if(cnt ==10 ||//первое нажатие, антидребезг 10 циклов
( cnt >= 70 && (cnt % 20)==10 ))//длительность паузы перед автоповтором (70)
//и  период автоповтора (20)
{
//здесь исполняем нажатие

}

cnt++;//инкремент счетчика
}
else cnt=0;//сброс счетчика

//бла-бла
}
Название: Re: Исходники, алгоритмы.
Отправлено: AlekseiKO от 19 Апрель 2016, 01:11:30
Попробывал еще одну кнопку от мышки. Такая же хня...
Попробывал поставить сначало :
кондер 0.01- без изменений
Выпаял 1к - без изм.
Впаял 27к -без изм.
Поменял кондер 0.1-без изм.

Я так понимаю автар прошивки решил поглумиться...
Название:
Отправлено: slav0n от 19 Апрель 2016, 03:56:42
Цитата: "AlekseiKO"
Я так понимаю автар прошивки решил поглумиться...
возможно просто сбацал по-быстрому в протеусе и всё
Название: Re: Исходники, алгоритмы.
Отправлено: AlekseiKO от 19 Апрель 2016, 05:25:13
Кстати в архиве есть фаил протеуса. Только я в нем ни разу не работал!
Он своего рода исходник?
Название: Re: Исходники, алгоритмы.
Отправлено: slav0n от 19 Апрель 2016, 07:00:57
Цитата: "AlekseiKO"
Он своего рода исходник?
нет
Название: энкодер, код обработки
Отправлено: slav0n от 31 Июль 2017, 16:56:56
весьма простой код обработки энкодера,
вставляется в тело прерывания (ну, или куда вам вздумается).

static u8 old;
u8 clk=PINC&(1<<5),dir=PINC&(1<<4);//смотрим ноги
if(old&&clk==0){//ловим задний фронт
if(dir)DATA++;//тудом
else DATA--;//сюдом
}
old=clk;
Название:
Отправлено: lizard66 от 31 Июль 2017, 22:24:13
Цитата: "slav0n"
вставляется в тело прерывания
Может лучше old сделать volatile?
Название:
Отправлено: slav0n от 01 Август 2017, 02:48:54
зачем? мой компилятор тут совершенно не реагирует на этот модификатор
Название:
Отправлено: slav0n от 01 Август 2017, 11:39:58
кстати, очевидно, что сигнальные ноги энкодера совершенно равнозначны
вот код-эквивалент:
  static u8 old;
   u8 clk=PINC&(1<<4),dir=PINC&(1<<5);//смотрим ноги
   if(old&&!clk){//ловим задний фронт, здесь монопенисуально old&&clk==0
      if(!dir)DATA++;//тудом
      else   DATA--;//сюдом
   }
   old=clk;
Название:
Отправлено: lizard66 от 01 Август 2017, 20:26:40
Цитата: "slav0n"
зачем? мой компилятор тут совершенно не реагирует на этот модификатор
В случае иcпользования приведенного кода в прерьівании, каждьій раз когда old будет задействована в конструкции, ее значение будет обновляться в регистре из рамьі.
Название:
Отправлено: slav0n от 01 Август 2017, 21:37:06
хм... кто-нибудь разницу видит? я нет

static u8 old;
u8 clk=PINC&(1<<4),dir=PINC&(1<<5);
    2228: a3 b3       in r26, 0x13 ; 19
    222a: a0 71       andi r26, 0x10 ; 16
    222c: 33 b3       in r19, 0x13 ; 19
if(old&&!clk){//ловим задний фронт
    222e: 80 91 0b 01 lds r24, 0x010B
    2232: 88 23       and r24, r24
    2234: 09 f4       brne .+2       ; 0x2238 <__vector_11+0x10e>
    2236: 46 c0       rjmp .+140     ; 0x22c4 <__vector_11+0x19a>
    2238: aa 23       and r26, r26
    223a: 09 f0       breq .+2       ; 0x223e <__vector_11+0x114>
    223c: 43 c0       rjmp .+134     ; 0x22c4 <__vector_11+0x19a>
...........
old=clk;
    22c4: a0 93 0b 01 sts 0x010B, r26
volatile static u8 old;
u8 clk=PINC&(1<<4),dir=PINC&(1<<5);
    2228: a3 b3       in r26, 0x13 ; 19
    222a: a0 71       andi r26, 0x10 ; 16
    222c: 33 b3       in r19, 0x13 ; 19
if(old&&!clk){//ловим задний фронт
    222e: 80 91 0b 01 lds r24, 0x010B
    2232: 88 23       and r24, r24
    2234: 09 f4       brne .+2       ; 0x2238 <__vector_11+0x10e>
    2236: 46 c0       rjmp .+140     ; 0x22c4 <__vector_11+0x19a>
    2238: aa 23       and r26, r26
    223a: 09 f0       breq .+2       ; 0x223e <__vector_11+0x114>
    223c: 43 c0       rjmp .+134     ; 0x22c4 <__vector_11+0x19a>
...........
old=clk;
    22c4: a0 93 0b 01 sts 0x010B, r26
Название:
Отправлено: lizard66 от 01 Август 2017, 22:41:01
Цитата: "slav0n"
хм... кто-нибудь разницу видит? я нет

static u8 old;
u8 clk=PINC&(1<<4),dir=PINC&(1<<5);
    2228: a3 b3       in r26, 0x13 ; 19
    222a: a0 71       andi r26, 0x10 ; 16
    222c: 33 b3       in r19, 0x13 ; 19
if(old&&!clk){//ловим задний фронт
    222e: 80 91 0b 01 lds r24, 0x010B
    2232: 88 23       and r24, r24
    2234: 09 f4       brne .+2       ; 0x2238 <__vector_11+0x10e>
    2236: 46 c0       rjmp .+140     ; 0x22c4 <__vector_11+0x19a>
    2238: aa 23       and r26, r26
    223a: 09 f0       breq .+2       ; 0x223e <__vector_11+0x114>
    223c: 43 c0       rjmp .+134     ; 0x22c4 <__vector_11+0x19a>
...........
old=clk;
    22c4: a0 93 0b 01 sts 0x010B, r26
volatile static u8 old;
u8 clk=PINC&(1<<4),dir=PINC&(1<<5);
    2228: a3 b3       in r26, 0x13 ; 19
    222a: a0 71       andi r26, 0x10 ; 16
    222c: 33 b3       in r19, 0x13 ; 19
if(old&&!clk){//ловим задний фронт
    222e: 80 91 0b 01 lds r24, 0x010B
    2232: 88 23       and r24, r24
    2234: 09 f4       brne .+2       ; 0x2238 <__vector_11+0x10e>
    2236: 46 c0       rjmp .+140     ; 0x22c4 <__vector_11+0x19a>
    2238: aa 23       and r26, r26
    223a: 09 f0       breq .+2       ; 0x223e <__vector_11+0x114>
    223c: 43 c0       rjmp .+134     ; 0x22c4 <__vector_11+0x19a>
...........
old=clk;
    22c4: a0 93 0b 01 sts 0x010B, r26
Не в обработчике, а в основном приложении, где анализируется состояние old.

Мля, я гоню, DATA должен бьіть volatile :)
Название:
Отправлено: slav0n от 02 Август 2017, 04:13:17
Цитата: "lizard66"
я гоню, DATA должен бьіть volatile :)
про DATA отдельный разговор. Здесь я ее написал чисто условно, чтобы изобразить какое-то действие.
Название: Re: Исходники, алгоритмы.
Отправлено: slav0n от 25 Декабрь 2017, 13:02:43
Цитата: "lizard66"
Не в обработчике, а в основном приложении, где анализируется состояние old.

Мля, я гоню, DATA должен бьіть volatile :)

lizard66 быстренько понял свою ошибку, а я объясню для всех:
переменная old просто физически не может анализироваться в основном приложении, т.к. она объявлена в обработчике
Название: код энкодера с антидребезгом
Отправлено: slav0n от 13 Январь 2018, 13:54:00
мне тут на одной тусовке загоняли что дескать мой код 100% ловит дребезг, а конденсаторы параллельно контактам ставить низзя ("ток через них будет 30А и они быстро выйдут из строя"). От смешные, ей богу.
 Ну ладно, вот мод кода, уже с антидребезгом:
static u8 old, olddir;
u8 clk=PINC&(1<<4),dir=PINC&(1<<5);//смотрим ноги
 if(olddir==dir)
 if(old&&!clk){//ловим задний фронт, здесь монопенисуально old&&clk==0
      if(!dir)DATA++;//тудом
      else   DATA--;//сюдом
 }
old=clk;
olddir=dir;
Название: Win10 и WinAVR
Отправлено: slav0n от 24 Июнь 2018, 09:29:19
в связи с заменой жесткого диска поставил десятку вместо семерки, а компилятор WinAVR на десятке сходу и не заработал.
Для исправления ситуации заменяем старую этой dll  в utilsbin директории.
Название: алгоритм Б
Отправлено: slav0n от 16 Декабрь 2018, 19:29:31
на днях попалось мне в неких обсуждениях упоминание алгоритма Брезенхема (https://uk.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%91%D1%80%D0%B5%D0%B7%D0%B5%D0%BD%D1%85%D0%B5%D0%B9%D0%BC%D0%B0) применительно к  управлению мощностью.
Я резонно спросил - а нафига оно тут?
Мне ответили - "алгоритм Б" используют что-бы равномерно распределить импульсы по времени.
я спросил - а почему-бы просто время не разделить на количество импульсов?
в ответ мне задали встречный вопрос - а дальше?

а дальше, вместо пространных измышлений, я по-быстрому написал следующий код, равномерно распределяющий pwr по периоду Т, безо всяких "алгоритмов Б":
if(--cnt_T==0){
if(pwr>T/2){
pwr=T-pwr;
sig=0;
}else sig=1;
cnt_T=T;
cnt_p=pwr;
dt=T/pwr;
cnt_dt=dt;
}
PORT_out=~sig;
if(cnt_p--)
if(--cnt_dt==0){
cnt_dt=dt;
PORT_out=sig;
}
Название: Re: Исходники, алгоритмы.
Отправлено: slav0n от 26 Декабрь 2018, 05:00:59
скорость писания кода повлекла логическую ошибку.
фикс:
if(--cnt_T==0){
if(pwr>T/2){
pwr=T-pwr;
sig=0;
}else sig=1;
cnt_T=T;
cnt_p=pwr;
dt=T/pwr;
cnt_dt=dt;
}
PORT_out=~sig;
if(cnt_p)
if(--cnt_dt==0){
cnt_dt=dt;
PORT_out=sig;
                cnt_p--;
}
Название: Re: Исходники, алгоритмы.
Отправлено: slav0n от 28 Январь 2019, 08:36:59


Название: снова про энкодер
Отправлено: slav0n от 15 Февраль 2020, 05:37:03
Покажу вам универсальную функцию, которая успешно работает как для энкодера, так и для двух кнопок.
Тело:
void encoder_parameter_change(int* param, int limit, s8 step, u8 direct, u8* accelerator){

if(!direct) step = -step;

if(limit > 40){//ускоритель
if(++(*accelerator) > 10){
step *= 10;
if(*accelerator > 25) *accelerator = 25;
CNT_short_Beep = 5;
}
}

int dat = *param + step;
int min=0, max=limit;

if(dat > limit) dat = max;
else if(dat < 0)dat = min;
else
CNT_short_Beep = 1;

*param = dat;
}

Использование для енкодера:
static u8 oldclk, olddir;
u8 direct = PINC&(1<<4), clk = PINC&(1<<5);
if((olddir==direct) and (oldclk && !clk)){
encoder_parameter_change(Enc.ptdat, Enc.lim, Enc.stp, direct, &accelerator);
}
oldclk = clk;
olddir = direct;

для батонов:
if((FLAGS.key_first_pressed or CNT_btn_lngprs==0) and (BTN_COD==B_Up or BTN_COD==B_Down)){
static u8 accelerator;
if(FLAGS.key_first_pressed) accelerator =0;

encoder_parameter_change(Enc.ptdat, Enc.lim, Enc.stp, (BTN_COD==B_Up), &accelerator);

wait50ms();//delay quick repeat
}