Эмуляция сигнала ДПКВ 60-2

Следующая стадия энкодер!

Попробуй еще вот этот код. Если я правильно библиотеку на ТМ нашел, то этот код при FREQ меньше 1000 будет показывать ’ 900’ вместо ‘0900’ как у тебя первоначально сделано.

#include <TM1637.h>
// Определяем пины для подключения дисплея TM1637
#define CLK         8
#define DIO         9

#define wheel_len   240
#define pt_pin      A0
#define out1_pin    2
#define out2_pin    3

#define timeout     1000

uint32_t tick_delay, mill;
uint32_t FREQ = 900;        //rpm
uint16_t pt;
uint8_t digits[] = {0, 0, 0, 0};

// Создаем объект дисплея TM1637
TM1637 tm1637(CLK, DIO);

const char Table1[wheel_len] = {
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
};

// Функция "печати" FREQ на TM1637...
void print_freq(void) {
  tm1637.point(false);
  (digits[0] = (FREQ / 1000)) ? tm1637.display(0, digits[0]) : tm1637.display(0, 0x7F);        // тысячи (десятки км/ч)

  digits[1] = (FREQ / 100) % 10;  // сотни (единицы км/ч)
  tm1637.point(false);
  tm1637.display(1, digits[1]);

  digits[2] = (FREQ / 10) % 10;   // десятки (десятые км/ч)
  tm1637.point(false);  // Включаем точку для разделения целой и дробной части
  tm1637.display(2, digits[2]);

  digits[3] = FREQ % 10;          // единицы (сотые км/ч)
  tm1637.point(false);
  tm1637.display(3, digits[3]);
}

void setup() {

  pinMode(out1_pin, OUTPUT);
  pinMode(out2_pin, OUTPUT);

  // Инициализируем дисплей
  tm1637.init();
  tm1637.set(6); // Устанавливаем яркость дисплея (0-7)

  pt = analogRead(pt_pin);

  FREQ = map(pt, 0, 1024, 300, 5500);

  tick_delay = ((120000000UL / FREQ) / wheel_len);
  print_freq();
  mill = millis();
}

void loop() {

  for (uint8_t i = 0; i < wheel_len; i++) {
    digitalWrite(out1_pin, Table1[i]);
    digitalWrite(out2_pin, !Table1[i]);
    delayMicroseconds(tick_delay);
  }

  if (millis() - mill > timeout) {

    mill = millis();
    pt = analogRead(pt_pin);

    FREQ = map(pt, 0, 1024, 300, 5500);

    tick_delay = ((120000000UL / FREQ) / wheel_len);

    // Отображаем скорость на дисплее
    print_freq();
  }
}

Спать уже хочу, но вроде бы ошибок быть не должно (но это не точно :slight_smile: )

1 лайк

Автомобильные блоки не запускаются. Не могут “ переварить “ этот сигнал с ардуино. В осциллограмме переодически проскакивает больше двух пропущенных зубов. BOOM, в любом случае для меня это прорыв) Задействую две ардуинки. Одна с сигналом дпкв с поста №16, а другая с тм1637 будет отображать обороты. Еще раз спасибо. Тему можно закрывать.

А ну-ка вот этот еще код опробуй (попробуем всё-таки в одну ардуину “уложиться” :smiley: ) :

#include <TM1637.h>
// Определяем пины для подключения дисплея TM1637
#define CLK         8
#define DIO         9

#define wheel_len   240
#define pt_pin      A0
#define out1_pin    2
#define out2_pin    3
#define timeout     500

uint32_t tick_delay, FREQ = 5500;        //rpm
uint32_t pt, mill;
volatile uint8_t index = 0;

// Создаем объект дисплея TM1637
TM1637 tm1637(CLK, DIO);

const char Table1[wheel_len] = {
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
};

void setup() {
  
  cli(); // Запрещаем прерывания

  DDRD |= (1 << PD2);
  DDRD |= (1 << PD3);

  PORTD &= ~(1 << PD2);
  PORTD &= ~(1 << PD3);

  // Настройка режима CTC Timer1
  TCCR1A &= ~((1 << WGM10) | (1 << WGM11));
  TCCR1B &= ~((1 << WGM13));
  TCCR1B |= (1 << WGM12);

  // Настройка предделителя на 8 Timer1
  TCCR1B |= (1 << CS11);
  TCCR1B &= ~((1 << CS12) | (1 << CS10));

  // Разрешаем прерывание по совпадению с OCR1A
  TIMSK1 |= (1 << OCIE1A);

  pt = analogRead(pt_pin);

  FREQ = map(pt, 0, 1024, 300, 5500);

  // Устанавливаем значение для сравнения
  tick_delay = ((120000000UL / FREQ) / wheel_len) * 2;
  OCR1A = tick_delay;

  // Глобально разрешаем прерывания
  sei();
}



void loop() {

  if (millis() - mill > timeout) {

    mill = millis();
    pt = analogRead(pt_pin);

    FREQ = map(pt, 0, 1024, 300, 5500);

    tick_delay = ((120000000UL / FREQ) / wheel_len) * 2;
    OCR1A = tick_delay;

    // Разбиваем на отдельные цифры
    int8_t digits[] = {0, 0, 0, 0};
    digits[0] = FREQ / 1000;        // тысячи (десятки км/ч)
    digits[1] = (FREQ / 100) % 10;  // сотни (единицы км/ч)
    digits[2] = (FREQ / 10) % 10;   // десятки (десятые км/ч)
    digits[3] = FREQ % 10;          // единицы (сотые км/ч)

    // Отображаем скорость на дисплее
    tm1637.point(false);
    tm1637.display(0, digits[0]);
    tm1637.point(false);
    tm1637.display(1, digits[1]);
    tm1637.point(false);  // Включаем точку для разделения целой и дробной части
    tm1637.display(2, digits[2]);
    tm1637.point(false);
    tm1637.display(3, digits[3]);
  }
}

ISR(TIMER1_COMPA_vect) {

  if (Table1[index] == 0) {
    PORTD &= ~(1 << PD2);
    PORTD |= (1 << PD3);
  } else {
    PORTD |= (1 << PD2);
    PORTD &= ~(1 << PD3);
  }

  if (index++ >= wheel_len) {
    index = 0;
  }
}

Должен работать “как слива в ж…” (ну ты понял).
Генерацию я у себя проверил - идет. ТМ1637 у меня нет.
Но, конечно же, нужно с оборудованием проверить.
Работает по другому принципу - на прерывании Timer1 (16 бит). А значит генерации импульсов ничто из главного цикла (loop()) помешать не может )))

Мои данные компиляции (у меня Arduino Nano v2 на Atmega168):

Скетч использует 2450 байт (17%) памяти устройства. Всего доступно 14336 байт.
Глобальные переменные используют 370 байт (36%) динамической памяти, оставляя 654 байт для локальных переменных. Максимум: 1024 байт.

Он же с фильтрацией нуля в первом знакоместе TM1637 (работает ли - не знаю, от тебя ответа не было):

#include <TM1637.h>
// Определяем пины для подключения дисплея TM1637
#define CLK         8
#define DIO         9

#define wheel_len   240
#define pt_pin      A0
#define out1_pin    2
#define out2_pin    3
#define timeout     500

uint32_t tick_delay, FREQ = 5500;        //rpm
uint32_t pt, mill;
volatile uint8_t index = 0;

// Создаем объект дисплея TM1637
TM1637 tm1637(CLK, DIO);

const char Table1[wheel_len] = {
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
};

void setup() {

  cli(); // Запрещаем прерывания

  DDRD |= (1 << PD2);
  DDRD |= (1 << PD3);

  PORTD &= ~(1 << PD2);
  PORTD &= ~(1 << PD3);

  // Настройка режима CTC Timer1
  TCCR1A &= ~((1 << WGM10) | (1 << WGM11));
  TCCR1B &= ~((1 << WGM13));
  TCCR1B |= (1 << WGM12);

  // Настройка предделителя на 8 Timer1
  TCCR1B |= (1 << CS11);
  TCCR1B &= ~((1 << CS12) | (1 << CS10));

  // Разрешаем прерывание по совпадению с OCR1A
  TIMSK1 |= (1 << OCIE1A);

  pt = analogRead(pt_pin);

  FREQ = map(pt, 0, 1024, 300, 5500);

  // Устанавливаем значение для сравнения
  tick_delay = ((120000000UL / FREQ) / wheel_len) * 2;
  OCR1A = tick_delay;

  // Глобально разрешаем прерывания
  sei();
}



void loop() {

  if (millis() - mill > timeout) {

    mill = millis();
    pt = analogRead(pt_pin);

    FREQ = map(pt, 0, 1024, 300, 5500);

    tick_delay = ((120000000UL / FREQ) / wheel_len) * 2;
    OCR1A = tick_delay;

    // Разбиваем на отдельные цифры
    int8_t digits[] = {0, 0, 0, 0};
    (digits[0] = (FREQ / 1000)) ? tm1637.display(0, digits[0]) : tm1637.display(0, 0x7F);        // тысячи (десятки км/ч)
    digits[1] = (FREQ / 100) % 10;  // сотни (единицы км/ч)
    digits[2] = (FREQ / 10) % 10;   // десятки (десятые км/ч)
    digits[3] = FREQ % 10;          // единицы (сотые км/ч)

    // Отображаем скорость на дисплее
    tm1637.point(false);
    tm1637.display(1, digits[1]);
    tm1637.point(false);  // Включаем точку для разделения целой и дробной части
    tm1637.display(2, digits[2]);
    tm1637.point(false);
    tm1637.display(3, digits[3]);
  }
}

ISR(TIMER1_COMPA_vect) {

  if (Table1[index] == 0) {
    PORTD &= ~(1 << PD2);
    PORTD |= (1 << PD3);
  } else {
    PORTD |= (1 << PD2);
    PORTD &= ~(1 << PD3);
  }

  if (index++ >= wheel_len) {
    index = 0;
  }
}

Буду испытывать)

О результатах испытаний не забудь написать ))

Оба скетча отображают обороты на тм1637. Завтра проверю на блоках.

Второй при меньше 1000 в первом знакоместе что отображает?

Осциллограф не подключал. А индикатор так же показывает от 300 до 5500 об.

Так же?
По идеи первый должен показывать ‘0300’, а второй ‘ 300’ (то есть вообще ничего на первом знакоместе не зажигать)…

сейчас еще раз посмотрю.

Ааааа, я кое-что забыл. Сейчас исправлю.

Исправил #45, попробуй его сейчас.

Ноль пропал):+1:

Отлично. Тогда завтра жду информацию по совместимости с оборудованием ))

Хотел спросить. Немного не по теме. Ардуино нано не прошиваются у меня их 5-ть и не один не хочет. Скачал новую программу, установил драйвера под CH341. Пробовал и через OldBootloader. Не прошиваются и все.

Смотри маркировку CH340, если затёрта - это китайская подделка на китайский CH340 :smiley:
Купи программатор USBasp и прошивай им (через разъём ISP).

Написано CH340G.

Лучше отдельную тему создать по этим ардуино. Чтобы эту «не засирать»…)

Пятница, и надеюсь на обратную связь. В унынии пить пиво или с радости напицца )))