Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

Ответ
Опции темы
Непрочитано 17.07.2024, 11:43   #1
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Atmega128 вызов прерывания кнопкой

Добрый день! прошу помощи - написал код. По смысл такой - есть сервомашинка, работа машинки должна запускаться и останавливаться одной кнопкой. Когда нажимаю кнопку, серва запускается, а вот при повторном нажатии остановка не происходит(хотя должна после того как серва сделает полный цикл), срабатывает только после удержания кнопки некоторое время. и то не всегда, пробовал в протеусе

Нажмите, чтобы открыть спойлер

PHP код:
#define F_CPU 8000000UL
#include ‹avr/io.h›
#include ‹util/delay.h›
#include ‹stdlib.h›
#include ‹avr/interrupt.h›
#include "n5110.h"

#define SERVO_MIN 1000  // Минимальная ширина импульса (1 мс)
#define SERVO_MAX 2000  // Максимальная ширина импульса (2 мс)

volatile uint16_t rotation_count 0;  // Счетчик количества поворотов
volatile char system_state 0;  // Состояние системы: 0 - выключено, 1 - включено

void button_init()
{
    
DDRD &= ~(‹‹ PIND2);  // Установка PD2 как вход
    
PORTD |= (‹‹ PIND2);  // Включение подтягивающих резисторов для PD2
    
EICRA |= (‹‹ ISC01) | (‹‹ ISC11);  // Срабатывание прерываний по спадающему фронту сигнала
    
EIMSK |= (‹‹ INT0) | (‹‹ INT1);   // Разрешение внешних прерываний INT0 и INT1
}

// Обработчик прерывания для INT0 (Запуск)
ISR(INT0_vect)
{
    
_delay_ms(10); // Защита от дребезга
    
system_state 0// Включение системы
}

// Обработчик прерывания для INT1 (Остановка)
ISR(INT1_vect)
{
    
_delay_ms(50); // Защита от дребезга
    
system_state 0// Выключение системы
}

void displey_start(void)
{
    
DDRB  &= ~((1‹‹PINB0) | (1‹‹PINB1) | (1‹‹PINB2) | (1‹‹PINB3) | (1‹‹PINB4));
    
PORTB 0x00;
    
Lcd_init();
    
Lcd_clear();
    
Lcd_update();
    
LcdContrast(62);
}

void servo_init()
{
    
TCCR1A |= (‹‹ WGM11) | (‹‹ COM1A1);  // Fast PWM, 10-bit
    
TCCR1B |= (‹‹ WGM12) | (‹‹ WGM13) | (‹‹ CS11);  // Предделитель 8
    
ICR1 20000;  // TOP значение для 20 мс периода (50 Гц)
    
DDRB |= (‹‹ PINB5);  // Установка PB5 (OC1A) как выход
}

void servo_set_position(uint16_t position)
{
    
OCR1A position;
}


int main(void)
{
    
sei();
    
servo_init();
    
displey_start(); // Запуск дисплея
    
button_init(); // Инициализация кнопки

    
uint8_t prev_button_state 0// Предыдущее состояние кнопки
    // Обновление дисплея
    
Lcd_clear();
    
char buff[20];
    
itoa(rotation_countbuff10);
    
Lcd_print(00FONT_1X, (unsigned char *)"серва");
    
Lcd_print(01FONT_1X, (unsigned char *)"запущена:");
    
Lcd_print(02FONT_1X,(unsigned char *)buff);
    
Lcd_print(42FONT_1X, (unsigned char *)" раз");
    
Lcd_update();
    

    while (
1)
    {
        
uint8_t current_button_state PIND & (‹‹ PIND2); // Текущее состояние кнопки

        // Проверка на нажатие кнопки (переход с 1 на 0)
        
if (!current_button_state && prev_button_state)
        {
            
            
system_state = !system_state// Переключение состояния системы
            
_delay_ms(20); // Простая защита от дребезга
        
}
        
        
prev_button_state current_button_state// Обновление предыдущего состояния кнопки

        
if (system_state// Если система включена
        
{
            
// Поворот сервомотора на полный угол
            
servo_set_position(SERVO_MIN);
            
_delay_ms(700);  // Задержка 700 мс

            // Поворот сервомотора обратно
            
servo_set_position(SERVO_MAX);
            
_delay_ms(700);  // Задержка 700 мс

            // Увеличение счетчика поворотов после завершения полного цикла
            
rotation_count++;

            
itoa(rotation_countbuff10);
            
Lcd_print(02FONT_1X,(unsigned char *)buff);
            
Lcd_update();
        }

    }

    return 
0;

Реклама:

Последний раз редактировалось Devil Byte; 17.07.2024 в 14:28.
Devil Byte вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 12:08   #2
mtit
Почётный гражданин KAZUS.RU
 
Аватар для mtit
 
Регистрация: 21.03.2007
Адрес: М.(осква)
Сообщений: 4,243
Сказал спасибо: 2,092
Сказали Спасибо 1,704 раз(а) в 965 сообщении(ях)
mtit на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

Схема где?
" _delay_ms(700)" в основном теле программы - в это время Ваша программа тупо ни на что реагировать не будет.
По моему - программа делает именно то, что запрограммировано.
__________________
+ 7 903 641 87 25// 1. Иногда отвечаю "по памяти" 2. Часто заблуждаюсь >> Критикуйте, не обижусь.
mtit вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 12:21   #3
ForcePoint
Почётный гражданин KAZUS.RU
 
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,926
Сказал спасибо: 2,986
Сказали Спасибо 3,163 раз(а) в 2,147 сообщении(ях)
ForcePoint на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

Сообщение от Devil Byte Посмотреть сообщение
.....
.....
volatile char system_state = 0; // Состояние системы: 0 - выключено, 1 - включено
.....
.....
// Обработчик прерывания для INT0 (Запуск)
ISR(INT0_vect)
{
_delay_ms(10); // Защита от дребезга
system_state = 0; // Включение системы
}
.....
.....
Проверяйте логику.
Хотя, конечно, этот говнокод с delay в прерывании надо переделывать полностью.
__________________
Экзорцист 40-го уровня.
ForcePoint вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 14:19   #4
mtit
Почётный гражданин KAZUS.RU
 
Аватар для mtit
 
Регистрация: 21.03.2007
Адрес: М.(осква)
Сообщений: 4,243
Сказал спасибо: 2,092
Сказали Спасибо 1,704 раз(а) в 965 сообщении(ях)
mtit на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

ForcePoint, неееее.
Цитата:
if (!current_button_state && prev_button_state)
{

system_state = !system_state; // Переключение состояния системы
_delay_ms(20); // Простая защита от дребезга
}
__________________
+ 7 903 641 87 25// 1. Иногда отвечаю "по памяти" 2. Часто заблуждаюсь >> Критикуйте, не обижусь.
mtit вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 14:36   #5
ForcePoint
Почётный гражданин KAZUS.RU
 
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,926
Сказал спасибо: 2,986
Сказали Спасибо 3,163 раз(а) в 2,147 сообщении(ях)
ForcePoint на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

Сообщение от mtit Посмотреть сообщение
неееее.
Я ничего не предлагал. Я просто подсветил, что Devil Byte вместо включения - выключает. Неисправленная копипаста, наверное.
Не говоря о том, что с т.з. пальцетыка и дребезга - 10 и 50 мс практически неотличимы.
__________________
Экзорцист 40-го уровня.
ForcePoint вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 14:39   #6
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

Сообщение от ForcePoint Посмотреть сообщение
Проверяйте логику.
Хотя, конечно, этот говнокод с delay в прерывании надо переделывать полностью.
То что вы принимайте за ошибку не имеет ни какого основания, так как нажатие кнопки в любом случае изменит статус на нужный. о дилеях - контроллер не производит ни какой вычислительной деятельности кроме счета одной переменной, поэтому без разницы использовать неблокирующую задержки или использовать простой дилей, вообще побоку что он простоит там несколько тысяч тактов. И использование очередного таймера не решит вопрос с кнопкой. Касательно дребезга и 10 и 50мс достаточно более чем при нормальных кнопках и соответствующей обвязке. Так что в принципе ваше пояснение дерьмо.

Последний раз редактировалось Devil Byte; 17.07.2024 в 17:06.
Devil Byte вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 18:15   #7
andries5
Почётный гражданин KAZUS.RU
 
Регистрация: 19.02.2008
Сообщений: 1,801
Сказал спасибо: 124
Сказали Спасибо 602 раз(а) в 419 сообщении(ях)
andries5 на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

Сообщение от Devil Byte Посмотреть сообщение
uint8_t current_button_state = PIND & (1 ‹‹ PIND2); // Текущее состояние кнопки

// Проверка на нажатие кнопки (переход с 1 на 0)
if (!current_button_state && prev_button_state)
{

system_state = !system_state; // Переключение состояния системы
_delay_ms(20); // Простая защита от дребезга
}

prev_button_state = current_button_state; // Обновление предыдущего состояния кнопки


[/PHP]
[/SPOILER]
То есть проверки состояния кнопки после delay нет. Я бы проверил состояние кнопки, _delay_ms(20);, а потом вновь проверка и утверждение о
system_state = !system_state; // Переключение состояния системы
andries5 вне форума   Ответить с цитированием
Непрочитано 17.07.2024, 18:50   #8
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

andries5, Типа вот так ?

Нажмите, чтобы открыть спойлер
PHP код:
        uint8_t current_button_state PIND & (‹‹ PIND2); // Текущее состояние кнопки

        // Проверка на нажатие кнопки (переход с 1 на 0)
        
if (!current_button_state && prev_button_state && !button_pressed)
        {
            
system_state = !system_state// Переключение состояния системы
            
button_pressed 1// Установка флага нажатия кнопки
            
_delay_ms(50); // Простая защита от дребезга
        
}
        else if (
current_button_state && button_pressed)
        {
            
// Если кнопка отпущена, сбросить флаг нажатия
            
button_pressed 0;
            
_delay_ms(50); // Задержка для стабилизации состояния кнопки
        


Попробовал, но смысл такой что все равно для того что бы серва остановилась Нужно выгадать момент когда начнется движение и нажать с удержанием кнопку до момента как она повернется в +90 градусов((. Хотя даже не преследую цели тормозить ее на любом угле, мне даже удобней если она завершает полный цикл, а потом останавливается

Последний раз редактировалось Devil Byte; 17.07.2024 в 19:02.
Devil Byte вне форума   Ответить с цитированием
Непрочитано 18.07.2024, 13:24   #9
andries5
Почётный гражданин KAZUS.RU
 
Регистрация: 19.02.2008
Сообщений: 1,801
Сказал спасибо: 124
Сказали Спасибо 602 раз(а) в 419 сообщении(ях)
andries5 на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

PHP код:
// Проверка на нажатие кнопки (переход с 1 на 0)
        
if (!current_button_state && prev_button_state)
        {
            
            
system_state = !system_state// Переключение состояния системы
            
_delay_ms(20); // Простая защита от дребезга
        
}
        
        
prev_button_state current_button_state// Обновление предыдущего состояния кнопки 
Думаю так лучше

PHP код:
// // Проверка на нажатие кнопки (переход с 1 на 0)
        
if (!current_button_state && prev_button_state)
        {
            
_delay_ms(50); // Простая защита от дребезга
            
{
                if (!
current_button_state && prev_button_state)
                {            
                    
system_state = !system_state// Переключение состояния системы
                    
prev_button_state current_button_state// Обновление предыдущего состояния кнопки
                
}                
            }
        } 
Зачем в прерывании _delay_ms(10); // Защита от дребезга ?
Непонятно.
system_state = 0; // Включение системы
system_state = 0; // Выключение системы
Тоже непонятно.

PHP код:
//
// Обработчик прерывания для INT0 (Запуск)
ISR(INT0_vect)
{
    
_delay_ms(10); // Защита от дребезга
    
system_state 0// Включение системы
}

// Обработчик прерывания для INT1 (Остановка)
ISR(INT1_vect)
{
    
_delay_ms(50); // Защита от дребезга
    
system_state 0// Выключение системы

А также _delay_ms(700); // Задержка 700 мс ?

PHP код:
//
// Поворот сервомотора на полный угол
            
servo_set_position(SERVO_MIN);
            
_delay_ms(700);  // Задержка 700 мс 
Возможно по прерыванию от кнопки Вы хотите остановить мотор? Непонятно.
А прерывание точно обрабатывается?
andries5 вне форума   Ответить с цитированием
Непрочитано 18.07.2024, 13:32   #10
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Atmega128 вызов прерывания кнопкой

andries5, Спасибо за помощь. Решил проблему несколько иным путем. Просто создал функцию и сделал дополнительный флаг мотор раннинг, во втором таймере просто сделал счетчик одной миллисекунды, и использовал это для отслеживания работы. По сути это и есть контроль кнопки. У меня сейчас кроме протеуса под рукой ничего нет. Смогу проверить как домой прилечу, но в протеусе работает прекрасно
Нажмите, чтобы открыть спойлер

PHP код:
void check_button()
{
    static 
uint32_t last_debounce_time 0;
    if (!(
PIND & (‹‹ BUTTON_PIN)))
    { 
// Если кнопка нажата
        
if (!button_state && (ms_counter last_debounce_time › 50))
        { 
// Простое антидребезговое условие
            
button_state 1// Установка флага состояния кнопки
            
last_debounce_time ms_counter;
            
motor_running = !motor_running// Переключение состояния мотора
        
}
    }
    else
    {
        if (
button_state && (ms_counter last_debounce_time › 50))
        { 
// Простое антидребезговое условие
            
button_state 0// Сброс флага состояния кнопки
            
last_debounce_time ms_counter;
        }
    }
}

void motor_control()
{
    static 
uint32_t last_action_time 0;
    if (
motor_running)
    {
        if (
ms_counter last_action_time › 200)
        { 
// Примерный период в нужные ХХХ мс
            
static uint8_t position_flag 0;
            if (
position_flag)
            {
                
servo_set_position(SERVO_MIN);
                
position_flag 0;
            }
            else
            {
                
servo_set_position(SERVO_MAX);
                
position_flag 1;
            }
            
last_action_time ms_counter;
            
rotation_count++;
        }
    }


Последний раз редактировалось Devil Byte; 18.07.2024 в 13:37.
Devil Byte вне форума   Ответить с цитированием
Ответ

Закладки


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
STM32F4 discovery не срабатывают прерывания по I2C Kopranych ARM 10 29.11.2016 20:56
AT89C5131 прием и передача данных по USB rihkov AVR 14 15.11.2012 08:16
PIC16 TMR0 и TMR2 Slava-martyn Микроконтроллеры, АЦП, память и т.д 10 06.12.2011 01:58
Вход в прерывания для PIC микроконтроллеров dimmich Микроконтроллеры, АЦП, память и т.д 4 06.12.2009 17:17
Прерывания в ATmega128 Святослав Микроконтроллеры, АЦП, память и т.д 2 10.02.2006 16:28


Часовой пояс GMT +4, время: 17:22.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot