Обсуждаем контроллеры компании Atmel.
Ответить

Re: ATmega8/16: шим, управляемый энкодером

Ср янв 27, 2021 18:37:30

Специально с дребезгом энкодера вроде не борются, анализа текущего и предыдущего состояния хватает.

Re: ATmega8/16: шим, управляемый энкодером

Ср янв 27, 2021 19:53:12

Вот вам модели
:beer: спасибо :)) а как теперь их правильно добавить в программу? и ничего в ней не сломать?

Re: ATmega8/16: шим, управляемый энкодером

Чт янв 28, 2021 06:46:55

Скачал архивчик... сейчас гляну :beer:
Сам пользуюсь элементом "MOTOR-ENCODER" (раздел электромеханики) подаешь питание как на коллекторный мотор - получаешь выход как с енкодера (только он не контактный, а внутри к шинам питания привязан) (средний вывод не используется)
СпойлерИзображение


Добавлено after 14 minutes 27 seconds:
Странные какието цвета на модели осциллографа в этом проекте.... (перепутанные какието) не знаю, с чем это связано, но пока себе эти файлы добавлять не буду... продолжу по старинке мотор-енкодер использовать.
Вложения
enc.png
(67.01 KiB) Скачиваний: 181

Re: ATmega8/16: шим, управляемый энкодером

Чт янв 28, 2021 13:15:42

Ivanoff-iv писал(а):Странные какието цвета на модели осциллографа в этом проекте.... (перепутанные какието) не знаю, с чем это связано, но пока себе эти файлы добавлять не буду...
А еще там скрипт есть, а в нем "червь", и этот "червь" у вас расположен по пути
C:\ProgramData\Labcenter Electronics\Proteus 8 Professional\SAMPLES\Generator Scripts\
Вроде ясно написал
Dimon456 писал(а): один из библиотек самого протеуса

Re: ATmega8/16: шим, управляемый энкодером

Чт янв 28, 2021 19:27:25

код
Спойлер#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <avr/eeprom.h>

uint8_t EEMEM pwm1;
uint8_t EEMEM pwm2;

void init_pwm (void)
{

DDRD |= (1<<DDD6) ;
PORTD &= ~(1<<PORTD6);

DDRB |= (1<<DDB1);
PORTB &= ~ (1<<PORTB1);

TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A = eeprom_read_byte (&pwm1);
OCR0B=0x00;

TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1=0x00;
ICR1=0x00;
OCR1A = eeprom_read_byte (&pwm2);
OCR1B=0x00;
}


typedef struct soft_enc
{
bool status;
volatile uint8_t enc_state;
volatile int8_t enc_data;
volatile int8_t enc_last;
volatile int8_t enc_new;
volatile int8_t enc_diff;
volatile uint8_t enc_pin;
} soft_enc;

soft_enc encoder1;
soft_enc encoder2;

#define encoder_init(a) _encoder_init(&a)
void _encoder_init (soft_enc *_soft_enc)
{
DDRD &= ~(_soft_enc -> enc_pin);

PORTD |= (_soft_enc -> enc_pin);
}

uint8_t konvert (uint8_t data)
{
switch (data)
{
case 0: return 0;
case 1: return 1;
case 2: return 2;
case 3: return 3;
case 4: return 1;
case 8: return 2;
case 12: return 3;

default: return 0;
}
}

#define encoder_scan(a) _encoder_scan(&a)
void _encoder_scan (soft_enc *_soft_enc)
{
uint8_t New;
if (!_soft_enc -> status)
{
New = konvert (PIND & (_soft_enc -> enc_pin));

switch(_soft_enc -> enc_state)
{
case 2:
{
if(New == 3) _soft_enc -> enc_data++;
if(New == 0) _soft_enc -> enc_data--;
break;
}

case 0:
{
if(New == 2) _soft_enc -> enc_data++;
if(New == 1) _soft_enc -> enc_data--;
break;
}
case 1:
{
if(New == 0) _soft_enc -> enc_data++;
if(New == 3) _soft_enc -> enc_data--;
break;
}
case 3:
{
if(New == 1) _soft_enc -> enc_data++;
if(New == 2) _soft_enc -> enc_data--;
break;
}
}
_soft_enc -> enc_state = New;
}
}

#define KEY_NULL 0
#define KEY_1 1
#define KEY_2 2

#define THRESHOLD 20

volatile uint8_t pressedKey = 0;
volatile uint8_t comp = 0;

void skan_kn (void)
{
uint8_t key;

if ((PINC & (1<<PINC1))==0)
key = KEY_1;
else if ((PINC & (1<<PINC2))==0)
key = KEY_2;
else {
key = KEY_NULL;
}

if (key) {
if (comp == THRESHOLD) {
comp = THRESHOLD + 10;
pressedKey = key;
return;
}
else if (comp < (THRESHOLD+5)) comp++;

}
else comp=0;

}

uint8_t get_key(void)
{
uint8_t key = pressedKey;
pressedKey = KEY_NULL;
return key;
}

void kn_init (void)
{

DDRC &= ~((1<<DDC2) | (1<<DDC1) | (1<<DDC0));
PORTC |= (1<<PORTC2) | (1<<PORTC1);
PORTC &= ~(1<<PORTC0);

EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (1<<PCIE1) | (0<<PCIE0);
PCMSK1=(0<<PCINT14) | (0<<PCINT13) | (0<<PCINT12) | (0<<PCINT11) | (0<<PCINT10) | (0<<PCINT9) | (1<<PCINT8);
PCIFR=(0<<PCIF2) | (1<<PCIF1) | (0<<PCIF0);

sei();
}


void init_timer2 (void)
{
//Timer Period: 0.5ms
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (1<<CS22) | (1<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0xF9;
OCR2B=0x00;
//Timer/Counter 2 Interrupt (s) initialisation
TIMSK2=(0<<OCIE2B) | (1<<OCIE2A) | (0<<TOIE2);

sei();
}

ISR(TIMER2_COMPA_vect)
{
encoder_scan(encoder1);
encoder_scan(encoder2);
}

ISR(PCINT1_vect)
{
if((PINC & (1<<(PINC0))) == 0)
{
cli();
eeprom_update_byte(&pwm1,OCR0A);
eeprom_update_byte(&pwm2,OCR1A);
OCR0A = 0;
OCR1A = 0;
while (1) {};
}

}

#define enc_relative(a) _enc_relative(&a)
int8_t _enc_relative(soft_enc *_soft_enc)
{
_soft_enc -> enc_new = _soft_enc -> enc_data / 4;
_soft_enc -> enc_diff = (int8_t)(_soft_enc -> enc_new - _soft_enc -> enc_last);
_soft_enc -> enc_last = _soft_enc -> enc_new;
return _soft_enc -> enc_diff;
}


int main()
{ uint8_t as; int8_t tm;

encoder1.enc_pin = (1<<PIND1) | (1<<PIND0);
encoder2.enc_pin = (1<<PIND3) | (1<<PIND2);
encoder_init(encoder1);
encoder_init(encoder2);

kn_init();

init_pwm();

init_timer2();

while (1)
{
tm = enc_relative(encoder1);
if(tm > 0) { if(OCR0A != 254) OCR0A++; }
if(tm < 0) { if(OCR0A != 0) OCR0A--; }

tm = enc_relative(encoder2);
if(tm > 0) { if(OCR1A != 254) OCR1A++; }
if(tm < 0) { if(OCR1A != 0) OCR1A--; }

skan_kn();
as = get_key();
if (as == KEY_1) encoder1.status = !encoder1.status;
if (as == KEY_2) encoder2.status = !encoder2.status;
}
}

СпойлерИзображение

поставил энкодеры из скрипта или скрипты из энкодеров и кручу их типа в разные стороны... кнопки нажимаю/отжимаю... вольтметры по нулям... может изъять эти злосчастные кнопки из кода :dont_know: Кху Ям

Re: ATmega8/16: шим, управляемый энкодером

Чт янв 28, 2021 21:20:24

Покажите настройки Атмеги168 ?
И осциллограмму с выходов ШИМ надо смотреть или регистры OCR0A и OCR1AL.
Надо для отладки учиться пользоваться файлом elf.
Прерывание таймера 0,5mc много, 1ms желательно.
И это плохая модель энкодеров, но как-то работает, можно на них в протеусе, больше всех понравилось модель на Атмега8, ближе к реальности.

На кнопки не нажимать, при включении контроллера энкодеры не блокированы.

Re: ATmega8/16: шим, управляемый энкодером

Пт янв 29, 2021 09:32:39

СпойлерИзображение
на выходах таймеров
СпойлерИзображение

а где же лежит мануаль на файлы эльф?

Re: ATmega8/16: шим, управляемый энкодером

Пт янв 29, 2021 10:13:43

Вам мануал на контроллер почитать надо, почитайте хотя бы про фьюзы.
Я несколько раз упоминал 16МГц, у вас результирующая не 16МГц.

Re: ATmega8/16: шим, управляемый энкодером

Пт янв 29, 2021 18:18:01

код не компилируется
Спойлер/*
* encoder.c
*
* Created: 29.01.2021 15:49:00
* Author : admin
*/
#define F_CPU 160000000UL
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <avr/cpufunc.h>
#include <avr/eeprom.h>

uint8_t EEMEM pwm1;
uint8_t EEMEM pwm2;

void init_pwm (void)
{

DDRD |= (1<<DDD6) ;
PORTD &= ~(1<<PORTD6);

DDRB |= (1<<DDB1);
PORTB &= ~ (1<<PORTB1);

TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A = eeprom_read_byte (&pwm1);
OCR0B=0x00;

TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1=0x00;
ICR1=0x00;
OCR1A = eeprom_read_byte (&pwm2);
OCR1B=0x00;
}


typedef struct soft_enc
{
bool status;
volatile uint8_t enc_state;
volatile int8_t enc_data;
volatile int8_t enc_last;
volatile int8_t enc_new;
volatile int8_t enc_diff;
volatile uint8_t enc_pin;
} soft_enc;

soft_enc encoder1;
soft_enc encoder2;

#define encoder_init(a) _encoder_init(&a)
void _encoder_init (soft_enc *_soft_enc)
{
DDRD &= ~(_soft_enc -> enc_pin);

PORTD |= (_soft_enc -> enc_pin);
}

uint8_t konvert (uint8_t data)
{
switch (data)
{
case 0: return 0;
case 1: return 1;
case 2: return 2;
case 3: return 3;
case 4: return 1;
case 8: return 2;
case 12: return 3;

default: return 0;
}
}

#define encoder_scan(a) _encoder_scan(&a)
void _encoder_scan (soft_enc *_soft_enc)
{
uint8_t New;
if (!_soft_enc -> status)
{
New = konvert (PIND & (_soft_enc -> enc_pin));

switch(_soft_enc -> enc_state)
{
case 2:
{
if(New == 3) _soft_enc -> enc_data++;
if(New == 0) _soft_enc -> enc_data--;
break;
}

case 0:
{
if(New == 2) _soft_enc -> enc_data++;
if(New == 1) _soft_enc -> enc_data--;
break;
}
case 1:
{
if(New == 0) _soft_enc -> enc_data++;
if(New == 3) _soft_enc -> enc_data--;
break;
}
case 3:
{
if(New == 1) _soft_enc -> enc_data++;
if(New == 2) _soft_enc -> enc_data--;
break;
}
}
_soft_enc -> enc_state = New;
}
}

#define KEY_NULL 0
#define KEY_1 1
#define KEY_2 2

#define THRESHOLD 20

volatile uint8_t pressedKey = 0;
volatile uint8_t comp = 0;

void skan_kn (void)
{
uint8_t key;

if ((PINC & (1<<PINC1))==0)
key = KEY_1;
else if ((PINC & (1<<PINC2))==0)
key = KEY_2;
else {
key = KEY_NULL;
}

if (key) {
if (comp == THRESHOLD) {
comp = THRESHOLD + 10;
pressedKey = key;
return;
}
else if (comp < (THRESHOLD+5)) comp++;

}
else comp=0;

}

uint8_t get_key(void)
{
uint8_t key = pressedKey;
pressedKey = KEY_NULL;
return key;
}

void kn_init (void)
{

DDRC &= ~((1<<DDC2) | (1<<DDC1) | (1<<DDC0));
PORTC |= (1<<PORTC2) | (1<<PORTC1);
PORTC &= ~(1<<PORTC0);

EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (1<<PCIE1) | (0<<PCIE0);
PCMSK1=(0<<PCINT14) | (0<<PCINT13) | (0<<PCINT12) | (0<<PCINT11) | (0<<PCINT10) | (0<<PCINT9) | (1<<PCINT8);
PCIFR=(0<<PCIF2) | (1<<PCIF1) | (0<<PCIF0);

sei();
}


void init_timer2 (void)
{
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (1<<CS22) | (1<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0xFF;
OCR2B=0x00;

TIMSK2=(0<<OCIE2B) | (1<<OCIE2A) | (0<<TOIE2);

sei();
}

ISR(TIMER2_COMPA_vect)
{
encoder_scan(encoder1);
encoder_scan(encoder2);
}

ISR(PCINT1_vect)
{
if((PINC & (1<<(PINC0))) == 0)
{
cli();
eeprom_update_byte(&pwm1,OCR0A);
eeprom_update_byte(&pwm2,OCR1A);
OCR0A = 0;
OCR1A = 0;
while (1) {};
}

}

#define enc_relative(a) _enc_relative(&a)
int8_t _enc_relative(soft_enc *_soft_enc)
{
_soft_enc -> enc_new = _soft_enc -> enc_data / 4;
_soft_enc -> enc_diff = (int8_t)(_soft_enc -> enc_new - _soft_enc -> enc_last);
_soft_enc -> enc_last = _soft_enc -> enc_new;
return _soft_enc -> enc_diff;
}


int main()
{ uint8_t as; int8_t tm;

encoder1.enc_pin = (1<<PIND1) | (1<<PIND0);
encoder2.enc_pin = (1<<PIND3) | (1<<PIND2);
encoder_init(encoder1);
encoder_init(encoder2);

kn_init();

init_pwm();

init_timer2();

while (1)
{
tm = enc_relative(encoder1);
if(tm > 0) { if(OCR0A != 254) OCR0A++; }
if(tm < 0) { if(OCR0A != 0) OCR0A--; }

tm = enc_relative(encoder2);
if(tm > 0) { if(OCR1A != 254) OCR1A++; }
if(tm < 0) { if(OCR1A != 0) OCR1A--; }

skan_kn();
as = get_key();
if (as == KEY_1) encoder1.status = !encoder1.status;
if (as == KEY_2) encoder2.status = !encoder2.status;
}
}

ошибки
Спойлер------ Build started: Project: encoder, Configuration: Debug AVR ------
Build started.
Project "encoder.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\encoder.cproj" (target "Build" depends on it):
Task "RunCompilerTask"
Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 4 --output-sync
Building file: .././main.c
Invoking: AVR/GNU C Compiler : 5.4.0
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(46,2): error: unknown type name 'bool'
bool status;
^
.././main.c: In function 'kn_init':
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(176,2): warning: implicit declaration of function 'sei' [-Wimplicit-function-declaration]
sei();
^
.././main.c: At top level:
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(194,1): warning: return type defaults to 'int' [-Wimplicit-int]
ISR(TIMER2_COMPA_vect)
^
.././main.c: In function 'ISR':
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(194,1): warning: type of '__vector_7' defaults to 'int' [-Wimplicit-int]
.././main.c: At top level:
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(200,1): warning: return type defaults to 'int' [-Wimplicit-int]
ISR(PCINT1_vect)
^
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(200,1): error: redefinition of 'ISR'
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(194,1): info: previous definition of 'ISR' was here
ISR(TIMER2_COMPA_vect)
^
.././main.c: In function 'ISR':
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(200,1): warning: type of '__vector_4' defaults to 'int' [-Wimplicit-int]
ISR(PCINT1_vect)
^
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(204,3): warning: implicit declaration of function 'cli' [-Wimplicit-function-declaration]
cli();
^
"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields -DDEBUG -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include" -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega168p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega168p" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o" -o "main.o" ".././main.c"
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\Debug\Makefile(76,1): error: recipe for target 'main.o' failed
c:\users\admin\Documents\Atmel Studio\7.0\encoder\encoder\main.c(212,1): warning: control reaches end of non-void function [-Wreturn-type]
}
^
make: *** [main.o] Error 1
Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "encoder.cproj" -- FAILED.
Done building project "encoder.cproj" -- FAILED.

Build FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

СпойлерИзображение

Re: ATmega8/16: шим, управляемый энкодером

Пт янв 29, 2021 19:00:45

Вроде как: была пропущена какая-то цель из-за ложного условия, от этого зависит целевая сборка. ???
Я в Студии не селен, может что-то в настройках проекта изменили, попробуйте создать проект заново.
Инет на это говорит следующее
Спойлер
При перекомпиляции проекта Atmel Studio выдает ошибку наподобие "Целевой объект "PreBuildEvent" пропущен из-за невыполненного условия; выражение ('$(PreBuildEvent)'!='') равно (''!='')", и проект не компилируется.

Это просто глюк IDE Atmel Studio, связанный с ошибочной обработкой пустого списка событий до запуска сборки проекта (Pre-build event). Глюк можно обойти, если добавить ничего не значащее событие, которое есть, но ничего не делает. Для этого откройте свойства проекта, перейдите на закладку Build Events, нажмите кнопку Edit Pre-build и добавьте в список Pre-build event command line командную строку наподобие sleep 0, нажмите OK, сохраните проект.
Там еще картинки есть, но я сюда их вставлять не буду.

Re: ATmega8/16: шим, управляемый энкодером

Пт янв 29, 2021 21:52:36

не, код я не трогал... на одном компе скомпилировался, а на другом забастовка... я худею, дорогая редакция...

Re: ATmega8/16: шим, управляемый энкодером

Сб янв 30, 2021 06:51:58

Я бы то же хотел знать ответ на вопрос: по чему у меня на одном компе программа работает, а на другом отказывается запускаться, пишет - Память не может быть written.

Re: ATmega8/16: шим, управляемый энкодером

Сб янв 30, 2021 09:27:35

Как вариант. В свое время студия у меня работала чем то вроде тестера на вирусы, как только студия начинала вести себя подозрительно, я проверял свой комп на вирусы. В большинстве случаев так и было - вирус.
Скормите студии другой какой-нибудь проект, создайте проект пустышку, скажем, пином дрыгнуть. Начните с этого. Если заработает ищите отличия, почему на одном работает, на другом нет.

Re: ATmega8/16: шим, управляемый энкодером

Пн фев 15, 2021 23:06:35

продолжение марлезонского балета. эпизод 471. есть код энкодера в баскоме... а как бы он выглядел для атмел студии интерестно? шим в шпротеусе шимит от 0 до 100%. как бы его приспособить для С в студии :dont_know:
СпойлерИзображение Изображение
Вложения
Encoder.rar
(1.63 KiB) Скачиваний: 146

Re: ATmega8/16: шим, управляемый энкодером

Вт фев 16, 2021 09:40:14

Вроде от прерываний уходил, и к прерываниям возвращается?
Чем тот код не устроил?
СпойлерВот вам 1 видео

Вот 2 видео

Вот 3 видео

Все энкодеры перебрал, в 1 видео на частоте 1МГц, в 3 видео до 100.0%, это с шагом 0,1%.

Re: ATmega8/16: шим, управляемый энкодером

Вт фев 16, 2021 21:18:47

Чем тот код не устроил?
код не собирается... тяжело быть идиотом о-о-о как тяжело-о-о :facepalm: бл!...короче, я не могу им воспользоваться... а тот код, который я показал в виде hex _файла работает в атмеге_8... те баскомные каракули мне ещё более непонятны, чем эти атмеловские каракули Си... если б я их перевел в си-каракули для атмеловской студии и собрал бы, то я б там помаленьку бы разобрался что_к_чему
СпойлерИзображение

Re: ATmega8/16: шим, управляемый энкодером

Ср фев 17, 2021 13:33:56

посмотрел текст на бейсике. что-то там какая-то ерунда, по моему.
второй выход энкодера ни как не анализируется в прерывании.
да и условий анализа всего два, а у энкодера 4 состояния при вращении.
у меня сделано по прерыванию таймера. но я пишу на ассемблере.

Добавлено after 1 hour 33 minutes 37 seconds:
а вообще, поиск по "работа с энкодером avr" тебе вывалит кучу вариантов и на Си и на чем угодно.

Re: ATmega8/16: шим, управляемый энкодером

Сб май 22, 2021 13:50:52

код такой собрался в студии без ошибок
Спойлер#define F_CPU 16000000UL
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <avr/cpufunc.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>

uint8_t EEMEM pwm1;
uint8_t EEMEM pwm2;

void init_pwm (void)
{

DDRD |= (1<<DDD6) ;
PORTD &= ~(1<<PORTD6);

DDRB |= (1<<DDB1);
PORTB &= ~(1<<PORTB1);

TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A = eeprom_read_byte (&pwm1);
OCR0B=0x00;

TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1=0x00;
ICR1=0x00;
OCR1A = eeprom_read_byte (&pwm2);
OCR1B=0x00;
}


typedef struct soft_enc
{
char status;
volatile uint8_t enc_state;
volatile int8_t enc_data;
volatile int8_t enc_last;
volatile int8_t enc_new;
volatile int8_t enc_diff;
volatile uint8_t enc_pin;
} soft_enc;

soft_enc encoder1;
soft_enc encoder2;

#define encoder_init(a) _encoder_init(&a)
void _encoder_init (soft_enc *_soft_enc)
{
DDRD &= ~(_soft_enc -> enc_pin);

PORTD |= (_soft_enc -> enc_pin);
}

uint8_t konvert (uint8_t data)
{
switch (data)
{
case 0: return 0;
case 1: return 1;
case 2: return 2;
case 3: return 3;
case 4: return 1;
case 8: return 2;
case 12: return 3;

default: return 0;
}
}

#define encoder_scan(a) _encoder_scan(&a)
void _encoder_scan (soft_enc *_soft_enc)
{
uint8_t New;
if (!_soft_enc -> status)
{
New = konvert (PIND & (_soft_enc -> enc_pin));

switch(_soft_enc -> enc_state)
{
case 2:
{
if(New == 3) _soft_enc -> enc_data++;
if(New == 0) _soft_enc -> enc_data--;
break;
}

case 0:
{
if(New == 2) _soft_enc -> enc_data++;
if(New == 1) _soft_enc -> enc_data--;
break;
}
case 1:
{
if(New == 0) _soft_enc -> enc_data++;
if(New == 3) _soft_enc -> enc_data--;
break;
}
case 3:
{
if(New == 1) _soft_enc -> enc_data++;
if(New == 2) _soft_enc -> enc_data--;
break;
}
}
_soft_enc -> enc_state = New;
}
}

#define KEY_NULL 0
#define KEY_1 1
#define KEY_2 2

#define THRESHOLD 20

volatile uint8_t pressedKey = 0;
volatile uint8_t comp = 0;

void skan_kn (void)
{
uint8_t key;

if ((PINC & (1<<PINC1))==0)
key = KEY_1;
else if ((PINC & (1<<PINC2))==0)
key = KEY_2;
else {
key = KEY_NULL;
}

if (key) {
if (comp == THRESHOLD) {
comp = THRESHOLD + 10;
pressedKey = key;
return;
}
else if (comp < (THRESHOLD+5)) comp++;

}
else comp=0;

}

uint8_t get_key(void)
{
uint8_t key = pressedKey;
pressedKey = KEY_NULL;
return key;
}

void kn_init (void)
{

DDRC &= ~((1<<DDC2) | (1<<DDC1) | (1<<DDC0));
PORTC |= (1<<PORTC2) | (1<<PORTC1);
PORTC &= ~(1<<PORTC0);

EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (1<<PCIE1) | (0<<PCIE0);
PCMSK1=(0<<PCINT14) | (0<<PCINT13) | (0<<PCINT12) | (0<<PCINT11) | (0<<PCINT10) | (0<<PCINT9) | (1<<PCINT8);
PCIFR=(0<<PCIF2) | (1<<PCIF1) | (0<<PCIF0);

sei();
}


void init_timer2 (void)
{
//timer period 0.5ms
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (1<<CS22) | (1<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0xF9;
OCR2B=0x00;
//timer/counter 2 interrupt(s) init
TIMSK2=(0<<OCIE2B) | (1<<OCIE2A) | (0<<TOIE2);

sei();
}

ISR(TIMER2_COMPA_vect)
{
encoder_scan(encoder1);
encoder_scan(encoder2);
}

ISR(PCINT1_vect)
{
if((PINC & (1<<(PINC0))) == 0)
{
cli();
eeprom_update_byte(&pwm1,OCR0A);
eeprom_update_byte(&pwm2,OCR1A);
OCR0A = 0;
OCR1A = 0;
while (1) {};
}

}

#define enc_relative(a) _enc_relative(&a)
int8_t _enc_relative(soft_enc *_soft_enc)
{
_soft_enc -> enc_new = _soft_enc -> enc_data / 4;
_soft_enc -> enc_diff = (int8_t)(_soft_enc -> enc_new - _soft_enc -> enc_last);
_soft_enc -> enc_last = _soft_enc -> enc_new;
return _soft_enc -> enc_diff;
}


int main()
{ uint8_t as; int8_t tm;

encoder1.enc_pin = (1<<PIND1) | (1<<PIND0);
encoder2.enc_pin = (1<<PIND3) | (1<<PIND2);
encoder_init(encoder1);
encoder_init(encoder2);

kn_init();

init_pwm();

init_timer2();

while (1)
{
tm = enc_relative(encoder1);
if(tm > 0) { if(OCR0A != 254) OCR0A++; }
if(tm < 0) { if(OCR0A != 0) OCR0A--; }

tm = enc_relative(encoder2);
if(tm > 0) { if(OCR1A != 254) OCR1A++; }
if(tm < 0) { if(OCR1A != 0) OCR1A--; }

skan_kn();
as = get_key();
if (as == KEY_1) encoder1.status = !encoder1.status;
if (as == KEY_2) encoder2.status = !encoder2.status;
}
}

ничегошеньки не работает. на выходах вместо нулей сразу +5в.
СпойлерИзображение[url=https://img.radiokot.ru/files/37066/2isy6pl531.png]Изображение[/url]

Re: ATmega8/16: шим, управляемый энкодером

Пн май 31, 2021 13:14:14

на некотором суперфоруме некоторые индивидуумы меня забанили за маленький нигилизм в виде керамики параллельно контактам

Re: ATmega8/16: шим, управляемый энкодером

Пн май 31, 2021 17:18:17

Правильно. Конденсаторы на контактах не панацея. Потому что идёт обгорание контактов из за замыкания заряженного конденсатора. А также, дешевле программно решить антидребезг. Места на плате не надо. Конденсаторы покупать не надо.
Ответить