SHipa

Подключение и работа с энкодером

11 сообщений в этой теме

SHipa    0

Проблема с состовлением прошивки для энкодера (фирмы PEPPERL+FUCHS по данной программе выдает примерно 330-340 импульсов на оборот) линии данных подключил на int0 и int1 atmega8 прошивку пишe в codevision avr 
Включил прерывания int0 и int1 по любому изменению состояния и повешал на оба прерывания функцию обработки
void enkoder(){
    if((PIND.2==0)&&(PIND.3==0)){input = 0;
    }else if((PIND.2==1)&&(PIND.3==0)){input = 1;
    }else if((PIND.2==1)&&(PIND.3==1)){input = 2;
    }else if((PIND.2==0)&&(PIND.3==1)){input = 3;
    };
    if(input!=buf){
        switch(buf) {
            case 0:{
                if(input == 1) impuls++;
                if(input == 3) impuls--; 
                break;
            }case 1:{
                if(input == 2) impuls++;
                if(input == 0) impuls--;  
                break;
            }case 2:{
                if(input == 3) impuls++;
                if(input == 1) impuls--;  
                break;
            }case 3:{
                if(input == 0) impuls++;
                if(input == 2) impuls--; 
                break;
            };
            buf = input;
        };
    }; 
    ugol=impuls;
};

после того как вращаю энкодер и возвращаю его в обратное положение значение переменной impuls неправельное оно всегда больше 0 и с каждым вращением погрешность все больше 
подскажите что я делаю нетак.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Alex    484

Дребезг контактов учитываете ?
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
SHipa    0

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    248

Как только выполняется break, программа выходит из switch{}. Поэтому строчка

buf = input;

не работает. Её надо передвинуть за следующую фигурную скобку, иначе это присваивание никогда не исполняется.

  • Одобряю 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
SHipa    0
10 минут назад, Yurkin2015 сказал:

Как только выполняется break, программа выходит из switch{}. Поэтому строчка


buf = input;

не работает. Её надо передвинуть за следующую фигурную скобку, иначе это присваивание никогда не исполняется.

после перемещения отроки вообще все перестало работать  теперь 1-2 импульса на 1 оборот энкодера

попробую еще раз проверить осцилографом на дребезг и помехи

Изменено пользователем SHipa

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    484

Тут точно правильно :

1 час назад, SHipa сказал:

    if((PIND.2==1)&&(PIND.3==1)){input = 2;
    if((PIND.2==0)&&(PIND.3==1)){input = 3;

?

А

buf = input;

вынесите за switch. Иначе, как уже сказали выше, точно ничего работать не будет.

  • Одобряю 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    248

Да и много лишних телодвижений, эти input и buf тут совсем не нужны по-моему.

Надо сделать проще. Например так

void enkoder(){
    if(PIND.2==0)
    {
        if(PIND.3==0)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.3==0)ugol--;
        else ugol++;
    }
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    484

Ну buf, по всей видимости, нужен для сохранения предыдущего состояния.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    248

Да, чёт я погорячился. Надо использовать разные процедуры прерывания для разных входов.

Вот, пусть int0 для ноги PIND.2. Если на ноге фронт импульса и другая нога PIND.3 = 0, то прибавляем. Если спад импульса и другая нога = 1, то тоже прибавляем. В остальных случаях - вычитаем.

void enkoder0()
{
    if(PIND.2==1) 
   {
        if(PIND.3==0)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.3==1)ugol++;
        else ugol--;
    }
}

Аналогично для другого прерывания int1 для ноги PIND.3

void enkoder1()
{
   if(PIND.3==1)
    {   
        if(PIND.2==1)ugol++;
        else ugol--;
    }
    else
    {
        if(PIND.2==0)ugol++;
        else ugol--;
    }
}

 

Изменено пользователем Yurkin2015

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
SHipa    0

спасибо помогли переместил переменную и прерывания стояли по наростающему фронту поменял на любое изменение сигнала

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Похожие публикации

    • Автор: balistik
      Всем доброго времени суток. Я реальный нуб в ATMEGA. Могу более-менее понять чужой код и из кусков сделать целое. Вопрос такой: реально ли на ATMEGA8 сделать 2 ШИМ (таймер 1 и2) и внутреннее прерывание (по таймеру 0) для чтения данных с DS18B20 на 8Мгц чтобы еще осталось на опрос кнопок и небольшую логику? Я выложу пример кода. По отдельность: ШИМ, прерывания, логика, запись в ЕПРОМ работает. Собираю все вместе - не работает. Пробовал в Протеусе, тоже глючит, да и протеус тормозит. Может кто чего подскажет.
      //#define F_CPU 8000000UL // устанавливаем рабочую частоту контроллера #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/eeprom.h> #include "ds18x20.h" #include "onewire.h" #define MAXSENSORS 1 unsigned int tempint = 0; // переменная для целого значения температуры unsigned int subzero = 0; // переменная отрицательных значений температуры unsigned int clock = 0; //задержка для опроса датчика температуры unsigned int termo_error = 0; //флаг ошибки термодатчика unsigned char regim, R1_SHIBER, R1_VENT, R2_SHIBER, R2_VENT, R3_SHIBER, R3_VENT; //переменные режимов работы volatile char press = 0, pr = 0, pr1 = 0, set = 0; //дополнительные переменные для кнопок #define SHIBER_PB 1 //шибер подачи топлива #define SHIBER_PWM OCR1A #define VENT_PB 2 //вентилятор подачи воздуха #define VENT_PWM OCR1B #define LED1_ON PORTD |= _BV(PD3) // светодиод режим 1 #define LED1_OFF PORTD &= ~_BV(PD3) #define LED2_ON PORTD |= _BV(PD4) // светодиод режим 2 #define LED2_OFF PORTD &= ~_BV(PD4) #define LED3_ON PORTD |= _BV(PD6) // светодиод режим 3 #define LED3_OFF PORTD &= ~_BV(PD6) #define LED4_ON PORTD |= _BV(PD7) // светодиод 4 программирование #define LED4_OFF PORTD &= ~_BV(PD7) #define BUT_M PIND & (1 << PD1) // кнопка MENU #define BUT_U PIND & (1 << PD2) // кнопка UP #define BUT_D PIND & (1 << PD0) // кнопка DOWN unsigned char eep1 EEMEM; // режим работы unsigned char eep2 EEMEM; // режим 1 ШИМ вентилятор unsigned char eep3 EEMEM; //режим 1 ШИМ шибер unsigned char eep4 EEMEM; // режим 2 ШИМ вентилятор unsigned char eep5 EEMEM; // режим 2 ШИМ шибер unsigned char eep6 EEMEM; // режим 3 ШИМ вентилятор unsigned char eep7 EEMEM; // режим 3 ШИМ шибер unsigned char eep8 EEMEM; // флаг первого запуска uint8_t Temperature, szero; //-255 uint8_t nSensors, j; uint8_t cel_frac_bits; uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE]; uint8_t search_sensors(void) // поиск DS18B20 { uint8_t i; uint8_t id[OW_ROMCODE_SIZE]; uint8_t diff, nSensors; nSensors = 0; for( diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE && nSensors < MAXSENSORS ; ) { DS18X20_find_sensor( &diff, &id[0] ); if( diff == OW_PRESENCE_ERR ) { Temperature = 255; szero = 1; break; } if( diff == OW_DATA_ERR ) { Temperature = 255; szero = 1; break; } for (i=0; i<OW_ROMCODE_SIZE; i++) gSensorIDs[nSensors][i]=id[i]; nSensors++; } return nSensors; } void get_temp(int sensor){ // получаем температуру с датчиков DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL); DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL); j = gSensorIDs[0][sensor]; // family-code for conversion-routine if (DS18X20_read_meas_single(j, &szero, &Temperature, &cel_frac_bits) != DS18X20_OK) { //если не прочиталось то -255 Temperature = 255; szero = 1; } if (DS18X20_read_meas_single(j, &szero, &Temperature, &cel_frac_bits) != DS18X20_OK) { //если не прочиталось то -255 Temperature = 255; szero = 1; } tempint=(int)Temperature; subzero=(int)szero; } void pin_init(void) { //инициализация портов ШИМ DDRB |= (1<<SHIBER_PB) | (1<<VENT_PB); PORTB &= ~((1<<SHIBER_PB) | (1<<VENT_PB)); } void timer0_init(void) { //инициализация таймера для термодатчика TCCR0 |= (1<<CS00); TIMSK |= ( 1 << TOIE0); TCNT0 = 0xFF; } void timer1_init(void) { //инициализация таймера ШИМ шибера TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10); TCNT1 = 0x00; ICR1 = 0xFF; OCR1A = 0x00; OCR1B = 0x00; } void timer2_init(void) { //инициализация таймера ШИМ вентилятора TCCR2 |= (1 << COM21) | (1 << WGM21) | (1 << WGM20) | (1 << CS20); TCNT2 = 0x00; OCR2 = 0x00; } ISR(TIMER0_OVF_vect){ //прерывание таймера 0 для термодатчика if (clock != 4294967295){_delay_us(50);clock++;}else{get_temp(0);clock=0;} } //***************** обработка нажатия кнопок ********************** void buttons(){ if(~BUT_U){if(set == 0)pr++; // кнопка UP if(pr == 10){ // долгое нажатие } _delay_ms(100); }else{ if(pr >= 1 && pr < 10){ // короткое нажатие regim++; if (regim>3){regim=0;} eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom set = 0; pr = 0; } pr = 0; } if(~BUT_D){if(set == 0)pr1++; // кнопка DOWN if(pr1 == 10){ // длинное нажатие } _delay_ms(100); }else{ if(pr1 >= 1 && pr1 < 10){ // короткое нажатие. //set = 20; regim--; if (regim<0){regim=3;} eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom _delay_ms(100); set = 0; pr1 = 0; } pr1 = 0; } if(~BUT_M){ // кнопка MENU press++; if(press == 1 && set != 0){set++;} // переход по настройкам if(press >= 100 && set == 0){set = 1; _delay_ms(200);} // ход в настройки if(set == 1) eeprom_write_byte(&eep2, R1_VENT); if(set == 2) eeprom_write_byte(&eep3, R1_SHIBER); if(set == 3) eeprom_write_byte(&eep4, R2_VENT); if(set == 4) eeprom_write_byte(&eep5, R2_SHIBER); if(set == 5) eeprom_write_byte(&eep6, R3_VENT); if(set == 6) eeprom_write_byte(&eep7, R3_SHIBER); if(set > 6){ _delay_ms(100); set = 0; press = 0;} // если включена настройка даты, }else{ if(set == 0 && press >= 1){ // если не вошли в настройки regim++; if (regim>3){regim=0;} eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom } press = 0; } } //*****************режим настроек******************** void settings(){ //визуальное подтверждение настроек if(press >= 1 && set == 1) { LED1_ON; LED2_OFF; LED3_OFF; LED4_ON; SHIBER_PWM = R1_VENT;} //ШИМ шибер 0-255 if(press >= 1 && set == 2) { LED1_ON; LED2_OFF; LED3_OFF; LED4_ON; VENT_PWM = R1_SHIBER;} //ШИМ вентилятор 0-255 if(press >= 1 && set == 3) { LED1_OFF; LED2_ON; LED3_OFF; LED4_ON; SHIBER_PWM = R2_VENT;} //ШИМ шибер 0-255 if(press >= 1 && set == 4) { LED1_OFF; LED2_ON; LED3_OFF; LED4_ON; VENT_PWM = R2_SHIBER;} //ШИМ вентилятор 0-255 if(press >= 1 && set == 5) { LED1_OFF; LED2_OFF; LED3_ON; LED4_ON; SHIBER_PWM = R3_VENT;} //ШИМ шибер 0-255 if(press >= 1 && set == 6) { LED1_OFF; LED2_OFF; LED3_ON; LED4_ON; VENT_PWM = R3_SHIBER;} //ШИМ вентилятор 0-255 switch(set) // включена настройка { case 1: // настройка R1_VENT if(~BUT_U){R1_VENT++; if(R1_VENT > 254) R1_VENT = 0; _delay_ms(100);} if(~BUT_D){R1_VENT--; if((~BUT_D) && R1_VENT == 0) R1_VENT = 254; _delay_ms(100);} break; case 2: // настройка R1_SHIBER if(~BUT_U){R1_SHIBER++; if(R1_SHIBER > 254) R1_SHIBER = 0; _delay_ms(100);} if(~BUT_D){R1_SHIBER--; if((~BUT_D) && R1_SHIBER == 0) R1_SHIBER = 254; _delay_ms(100);} break; case 3: // настройка R2_VENT if(~BUT_U){R2_VENT++; if(R2_VENT > 254) R2_VENT = 0; _delay_ms(100);} if(~BUT_D){R2_VENT--; if((~BUT_D) && R2_VENT == 0) R2_VENT = 254; _delay_ms(100);} break; case 4: // настройка R2_SHIBER if(~BUT_U){R2_SHIBER++; if(R2_SHIBER > 254) R2_SHIBER = 0; _delay_ms(100);} if(~BUT_D){R2_SHIBER--; if((~BUT_D) && R2_SHIBER == 0) R2_SHIBER = 254; _delay_ms(100);} break; case 5: // настройка R3_VENT if(~BUT_U){R3_VENT++; if(R3_VENT > 254) R3_VENT = 0; _delay_ms(100);} if(~BUT_D){R3_VENT--; if((~BUT_D) && R3_VENT == 0) R3_VENT = 254; _delay_ms(100);} break; case 6: // настройка R3_SHIBER if(~BUT_U){R3_SHIBER++; if(R3_SHIBER > 254) R3_SHIBER = 0; _delay_ms(100);} if(~BUT_D){R3_SHIBER--; if((~BUT_D) && R3_SHIBER == 0) R3_SHIBER = 254; _delay_ms(100);} break; } } int main(){ /*******************************настройка переферии******************************/ cli(); ow_set_bus(&PIND, &PORTD, &DDRD, PD5); // иництализация протокола 1-wire nSensors = search_sensors(); // поиск датчиков DS18B20 DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL); //включаем преобразование температуры pin_init(); //timer0_init(); timer1_init(); timer2_init(); _delay_ms(5); if(eeprom_read_byte(&eep8) != 1){ // читаем eeprom, если там мусор (первый запуск), пишем свои данные eeprom_write_byte(&eep1, 0); // режим работы eeprom_write_byte(&eep2, 150); // режим 1 ШИМ вентилятор eeprom_write_byte(&eep3, 100); //режим 1 ШИМ шибер eeprom_write_byte(&eep4, 200); //режим 2 ШИМ вентилятор eeprom_write_byte(&eep5, 150); //режим 2 ШИМ шибер eeprom_write_byte(&eep6, 230); //режим 3 ШИМ вентилятор eeprom_write_byte(&eep7, 200); //режим 3 ШИМ шибер eeprom_write_byte(&eep8, 1); // флаг первого запуска } //читаем настройки из памяти regim = eeprom_read_byte(&eep1); // читаем режим работы из eeprom R1_VENT = eeprom_read_byte(&eep2); // читаем режим 1 ШИМ вентилятор из eeprom R1_SHIBER = eeprom_read_byte(&eep3); //читаем режим 1 ШИМ шибер R2_VENT = eeprom_read_byte(&eep4); //читаем режим 2 ШИМ вентилятор R1_SHIBER = eeprom_read_byte(&eep5); //читаем режим 2 ШИМ шибер R3_VENT = eeprom_read_byte(&eep6); //читаем режим 3 ШИМ вентилятор R1_SHIBER = eeprom_read_byte(&eep7); //читаем режим 3 ШИМ шибер sei(); _delay_ms(5); /**********************************инициализация ШИМ*************************************/ while(1){ //if (tempint=255) {LED1_ON;LED2_OFF;LED3_ON;termo_error=1;} else {termo_error=0;}//выводим код ошибки датчика темппературы buttons();//обработик нажатия кнопок if (termo_error == 0){//блокировка по термодатчику if(set == 0) { //нормальный режим работы if (regim == 0){ //режим работы 0 LED1_OFF; LED2_OFF; LED3_OFF; LED4_OFF; SHIBER_PWM = 0; //ШИМ шибер 0-255 VENT_PWM = 0; //ШИМ вентилятор 0-255 } if (regim == 1){ //режим работы 1 LED1_ON; LED2_OFF; LED3_OFF; LED4_OFF; VENT_PWM = R1_VENT; //ШИМ вентилятор 0-255 if (tempint >=40) { //блокировка по температуре SHIBER_PWM = 0; //ШИМ шибер 0-255 }else{ SHIBER_PWM = R1_SHIBER; //ШИМ шибер 0-255 } } if (regim == 2){ //режим работы 2 LED1_OFF; LED2_ON; LED3_OFF; LED4_OFF; VENT_PWM = R2_VENT; //ШИМ вентилятор 0-255 if (tempint >=60) { //блокировка по температуре SHIBER_PWM = 0; //ШИМ шибер 0-255 }else{ SHIBER_PWM = R2_SHIBER; //ШИМ шибер 0-255 } } if (regim == 3){ //режим работы 3 LED1_OFF; LED2_OFF; LED3_ON; LED4_OFF; VENT_PWM = R3_VENT; //ШИМ вентилятор 0-255 if (tempint >=80) { //блокировка по температуре SHIBER_PWM = 0; //ШИМ шибер 0-255 }else{ SHIBER_PWM = R3_SHIBER; //ШИМ шибер 0-255 } } } }else{ SHIBER_PWM=0; VENT_PWM=0; } if(set != 0) settings();//вход в настройки } //return 0; }  
    • Автор: Zabar31
       
      Всех приветствую! Вообщем ситуация такая - (сейчас будет предыстория) стал понемногу интересоваться МК и набрел на статью о подключении экрана нокии 3310 к атмеге8. Вот она http://cxem.net/mc/mc201.php  Сказать что заинтриговало - ничего не сказать... к тому же автор в комментариях написал, что можно поочередно выводить изображения, и таким образом создать анимацию. Так вот, к чему я, была у меня монохромная моторолла и на ней был прикольный "скринсейвер" с рыбками, теперь который я хочу воссоздать. Надписей "Hello, world!" я не планирую, а только чистый вывод изображений.
      Теперь сама суть моего обращения на форум.
      1) Так как в Bascom я начинающий, решил идти по пути наименьшего сопротивления, то есть немного подправив код в проэкте, предоставленный автором статьи. Подправить то я его подправил, но вот правильно ли... Вообщем мне бы хотелось чтобы знающие люди проверили бы мой код. Хотя Bascom компилирует код без проблем.
      Вот исходный код:
      Вот мой код: (на одинаковость стека изображений не обращайте внимания, мои в процессе воссоздания, а мне нужна проверка самого принципа вывода изображений, который я написал)
      Таким образом я хочу выводить изображения поочередно с интервалом в 1 секунду.
      2)Еще более интересующий меня вопрос - если открыть даташит на атмега8, то там написано, что флеш памяти для программ 8 кб. Но вот что интересно и вводит меня в ступор. Если просто взять проэкт автора статьи и скомпилировать его в .hex, то получаем: Bascom пишет при компиляции "Flash used - 55%", то есть как бы половина атмеги пустая, но вот выходной файл .hex имеет размер 13кб. Вот я и не могу понять как даже авторский проэкт в 13кб прошивается в атмегу с 8кб? Магия наверное. Скомпилировав "свой" проэкт, я получаю  "Flash used - 66%" и файл на 15кб. Вот и возник такой вопрос - это нормально и так и должно быть? А если нет - то как правильно скомпилировать?
      Так как пока проверить код в железе нет возможности (еще едет), вот к Вам, знающим людям, за помощью и обращаюсь. Ниже прикрепляю видеофайл с  компиляцией проэкта автора статьи в Bascom.
       clip0002.avi
       
    • Автор: oner
      Вопрос знатокам: можно ли без особых танцев с бубнами для выведения строчного текста вместо дисплея 1602 подключить 12864?  В идеале  используя то же количество проводов между контроллером и дисплеем. Контроллер Atmega8.
       
      И если можно, то как?
    • Автор: formvit
      Необходимо сделать рисунок или гравировку на полированном диске из нержавейки или алюминии с центральным отверстием по данному чертежу.
      Толщина диска 0,3 - 0,5 мм.
      120 чёрных и 120 зеркальных секторов.
      Точность отношения черного сектор к зеркальному 0,95 - 1,05.
      На сегодня необходимо 20 шт.
      все размеры в мм

    • Автор: oner
      Пишу программу для датчика освещенности, который должен по нажатию кнопки измерять напряжение на одном из портов своего АЦП и записывать измеренное значение (в вольтах) на SD-карту. При повторном нжатии на кнопку результат измерения должен записываться на карту в тот же файл, но на новую строку.
       
      Сопротивление фоторезистора в зависимости от освещенности изменяется пимерно от 0,5 до 25 кОм, поэтому в качестве второго резистора делителя напряжения, результат деления которого и замеряем, выбран 27 кОм, чтобы не перегружать вход АЦП.
      Собственно, а куда по схеме эту кнопку лучше ставить? На питание или на какой-нибудь порт?

       
      В коде отталкиваюсь от такого:
      #include <mega8.h> #include <stdio.h> #include <stdlib.h> #define ADC_VREF_TYPE 0x00 unsigned int result; unsigned int read_adc(unsigned char adc_input); // volatile unsigned int count; //счетчик скопированных данных { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization of the ADC input voltage delay_us(10); // Start the AD conversion ADCSRA|=0x40; // Wait for the AD conversion to complete while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCW; } #asm("sei") ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x81; while (1) { result=read_adc(0); result=(result*500L)/1024; // Тут мы измерили напряжение на резисторе if(disk_initialize()==0) //инициализируем флешку { FILE *file; //Открываем текстовый файл с правами на запись file = fopen("light.txt", "w+t"); //Пишем в файл fprintf(file, result); //Закрываем файл fclose(file); getch(); pf_mount(0x00); //демонтируем фат } }