ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Понедельник
21 апреля
1504010 Топик полностью
Andreas (06.03.2025 19:48, просмотров: 154) ответил Andreas на Ужасы нашего городка. После года работы иногда стали энкодеры(те, что руками крутишь) глючить. Решил посмотреть скопом и логанализатором и удивился, что вообще работает. Подтяжка 5к к питанию без конденсатора. Добавление конденсатора полностью решает проблему, но надо как-то доработать старое программно.
Спросил дика ЗЫ: ну не понимаю, как код тут оформить, со всякими тегами вставлял. ЗЗЫ: попросил на основе таблицы сделать - переписал послушно и тоже разумно. 

Напиши программу на С для обработки квадратурного энкодера в условиях сильных помех

Неплохой вариант


#include <stdbool.h>

#include <stdint.h>

#include <stdio.h>

// Параметры фильтра

#define FILTER_ORDER 4

#define DEBOUNCE_THRESHOLD 3

// Глобальные переменные для хранения состояния энкодера

volatile int32_t encoder_count = 0;

volatile uint8_t last_state = 0;

volatile uint8_t debounce_counter = 0;

// Функция для чтения текущего состояния энкодера (A и B каналы)

uint8_t read_encoder_state()

{

// Здесь должен быть код для чтения состояния пинов энкодера

// Например, для A и B каналов:

// uint8_t state = (PINB & 0x03); // Чтение первых двух битов порта B

// return state;

return 0; // Заглушка, замените на реальное чтение

}

// Функция для применения цифрового фильтра

uint8_t apply_filter(uint8_t new_state)

{

static uint8_t filter_buffer[FILTER_ORDER];

static uint8_t filter_index = 0;

// Добавляем новое значение в буфер

filter_buffer[filter_index] = new_state;

filter_index = (filter_index + 1) % FILTER_ORDER;

// Подсчитываем количество одинаковых значений в буфере

uint8_t count = 0;

for(uint8_t i = 0; i < FILTER_ORDER; i++)

{

if(filter_buffer[i] == new_state)

{

count++;

}

}

// Если количество одинаковых значений превышает порог, возвращаем новое состояние

if(count >= FILTER_ORDER / 2)

{

return new_state;

}

// Иначе возвращаем предыдущее состояние

return last_state;

}

// Функция для обработки сигналов энкодера

void process_encoder()

{

uint8_t current_state = read_encoder_state();

uint8_t filtered_state = apply_filter(current_state);

// Подавление дребезга

if(filtered_state != last_state)

{

debounce_counter++;

if(debounce_counter >= DEBOUNCE_THRESHOLD)

{

// Определение направления вращения

uint8_t state_change = (last_state << 2) | filtered_state;

switch(state_change)

{

case 0b0001:

case 0b0111:

case 0b1110:

case 0b1000:

encoder_count++; // Вращение по часовой стрелке

break;

case 0b0010:

case 0b1011:

case 0b1101:

case 0b0100:

encoder_count--; // Вращение против часовой стрелки

break;

default:

// Некорректное изменение состояния, игнорируем

break;

}

last_state = filtered_state;

debounce_counter = 0;

}

}

else

{

debounce_counter = 0;

}

}

int main()

{

// Инициализация (настройка пинов, таймеров и т.д.)

// ...

while(1)

{

// Основной цикл обработки

process_encoder();

// Вывод текущего значения счетчика энкодера

printf("Encoder count: %ld\n", encoder_count);

// Задержка для имитации работы в реальном времени

// (в реальной системе это может быть реализовано через прерывания)

// ...

}

return 0;

}