После создания блока FLprog код перестает работать

Ответить
VNL64T
Рядовой
Сообщения: 62
Зарегистрирован: 22 янв 2024, 05:37
Имя: Алекс
Благодарил (а): 2 раза
Поблагодарили: 6 раз

После создания блока FLprog код перестает работать

Сообщение VNL64T »

Добрый день. написал код для управления Шим, самостоятельно через IDE работает прекрасно, решил создать блок и тут тупик Может кто подскажет? или свежи взгляд ,,, СПАСИБО

Рабочий код...

Код: Выделить всё

/*==============================================================================
  DECLARE SECTION 
==============================================================================*/

#include <avr/interrupt.h>

// ===== НАСТРОЙКИ =====
const int pinT1 = 9;          // 9 (OC1A) или 10 (OC1B)
const int pinT2 = 3;          // 3 (OC2B) или 11 (OC2A)
volatile float Per = 50.0;    // Начальная частота [Гц]
volatile float pulseT1 = 2.5; // Начальная длительность T1 [мс]
volatile float pulseT2 = 10.2;// Начальная длительность T2 [мс]
volatile float phaseShift = -1.3; // Начальный сдвиг фазы [мс]

// ===== СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ =====
volatile bool isT2Active = false;
volatile uint16_t icr1_value, ocr1_value, ocr2_start, ocr2_pulse;
volatile uint8_t prescaler1, prescaler2_start, prescaler2_pulse;
bool use_OC1A = false;
bool use_OC2A = false;

// ===== ПРОТОТИПЫ ФУНКЦИЙ =====
bool validateParameters();
void configureTimers();
void setTimer1Prescaler(float period_us);
void setTimer1Registers();
uint16_t calculateTimer2(float ms, uint8_t* prescaler);
void handleT1Interrupt();
uint16_t scalerValueTimer1(uint8_t prescaler);
void updateParameters(float newPer, float newPulseT1, float newPulseT2, float newPhaseShift);
void updatePer(float newPer);
void updatePulses(float newPulseT1, float newPulseT2);
void updatePhaseShift(float newPhaseShift);

/*==============================================================================
  SETUP SECTION 
==============================================================================*/

void setup() {
  use_OC1A = (pinT1 == 9);
  use_OC2A = (pinT2 == 11);
  
  pinMode(pinT1, OUTPUT);
  pinMode(pinT2, OUTPUT);
  
  if (!validateParameters()) while(1); // Блокировка при ошибке
  configureTimers();
  sei(); // Разрешение прерываний
}

/*==============================================================================
  FUNCTION SECTION 
==============================================================================*/

bool validateParameters() {
  float period_ms = 1000.0 / Per;
  return !(
    (pinT1 != 9 && pinT1 != 10) || 
    (pinT2 != 3 && pinT2 != 11) ||
    (Per < 0.2 || Per > 1000.0) ||     // Диапазон частот
    (pulseT1 < 0.1 || pulseT2 < 0.1) || // Минимальная длительность
    (pulseT1 >= period_ms) ||           // T1 не должен заполнять весь период
    (pulseT1 + phaseShift + pulseT2 >= period_ms) // Наложение сигналов
  );
}

void configureTimers() {
  float period_us = 1e6 / Per;
  
  // Настройка Timer1 (16-битный)
  TCCR1A = TCCR1B = 0;
  setTimer1Prescaler(period_us);
  setTimer1Registers();

  // Настройка Timer2 (8-битный)
  TCCR2A = (use_OC2A) ? (1 << COM2A1) : (1 << COM2B1); // Режим сравнения
  TCCR2B = 0; // Предделитель пока выключен

  // Расчет параметров для Timer2
  float startTime = pulseT1 + phaseShift;
  ocr2_start = calculateTimer2(fabs(startTime), &prescaler2_start);
  ocr2_pulse = calculateTimer2(pulseT2, &prescaler2_pulse);

  // Настройка прерываний Timer1
  TIMSK1 = (1 << TOIE1) | ((phaseShift >= 0) ? 
          (use_OC1A ? (1 << OCIE1A) : (1 << OCIE1B)) : 0);
}

void setTimer1Prescaler(float period_us) {
  const float scalers[] = {1.0, 8.0, 64.0, 256.0, 1024.0};
  for(int i = 4; i >= 0; i--) {
    icr1_value = (period_us * 16.0 / scalers[i]) - 1;
    if(icr1_value <= 65535) {
      prescaler1 = (i == 4) ? 0x05 : (i == 3) ? 0x04 : 
                  (i == 2) ? 0x03 : (i == 1) ? 0x02 : 0x01;
      return;
    }
  }
  icr1_value = 65535; // Максимальное значение при ошибке
}

void setTimer1Registers() {
  TCCR1A = (1 << WGM11); // Fast PWM (ICR1)
  TCCR1B = (1 << WGM13) | (1 << WGM12) | prescaler1;
  
  // Расчет OCR1
  float ticks = (pulseT1 * 1000.0 * 16.0) / scalerValueTimer1(prescaler1);
  ocr1_value = constrain(ticks - 1, 1, icr1_value);

  // Настройка вывода
  TCCR1A &= ~((1 << COM1A1) | (1 << COM1B1));
  if(use_OC1A) {
    TCCR1A |= (1 << COM1A1); // Неинверсный режим
    OCR1A = ocr1_value;
  } else {
    TCCR1A |= (1 << COM1B1);
    OCR1B = ocr1_value;
  }
  ICR1 = icr1_value; // Установка периода
}

uint16_t calculateTimer2(float ms, uint8_t* prescaler) {
  const float scalers[] = {1.0, 8.0, 32.0, 64.0, 128.0, 256.0};
  float target_ticks = ms * 1000.0 * 16.0;
  
  for(uint8_t i = 0; i < 6; i++) {
    float val = target_ticks / scalers[i];
    if(val <= 256.0) {
      *prescaler = (i == 0) ? 0x01 : (i == 1) ? 0x02 : 
                  (i == 2) ? 0x03 : (i == 3) ? 0x04 : 
                  (i == 4) ? 0x05 : 0x07;
      return val - 1;
    }
  }
  return 255; // Максимальное значение
}

uint16_t scalerValueTimer1(uint8_t prescaler) {
  switch(prescaler) {
    case 0x01: return 1;
    case 0x02: return 8;
    case 0x03: return 64;
    case 0x04: return 256;
    case 0x05: return 1024;
    default: return 1;
  }
}

void updateParameters(float newPer, float newPulseT1, float newPulseT2, float newPhaseShift) {
  cli();
  float oldParams[4] = {Per, pulseT1, pulseT2, phaseShift};
  
  Per = newPer;
  pulseT1 = newPulseT1;
  pulseT2 = newPulseT2;
  phaseShift = newPhaseShift;

  if(!validateParameters()) { // Откат при ошибке
    Per = oldParams[0];
    pulseT1 = oldParams[1];
    pulseT2 = oldParams[2];
    phaseShift = oldParams[3];
  } else {
    configureTimers();
  }
  sei();
}

void updatePer(float newPer) {
  float newPulseT1 = (pulseT1 * Per) / newPer; // Сохранение скважности
  updateParameters(newPer, newPulseT1, pulseT2, phaseShift);
}

void updatePulses(float newPulseT1, float newPulseT2) {
  updateParameters(Per, newPulseT1, newPulseT2, phaseShift);
}

void updatePhaseShift(float newPhaseShift) {
  cli();
  while(isT2Active); // Ожидание завершения импульса T2
  updateParameters(Per, pulseT1, pulseT2, newPhaseShift);
}

/*==============================================================================
  INTERRUPT SECTION 
==============================================================================*/

ISR(TIMER1_COMPA_vect) { 
  if(phaseShift >= 0 && use_OC1A) handleT1Interrupt();
}

ISR(TIMER1_COMPB_vect) { 
  if(phaseShift >= 0 && !use_OC1A) handleT1Interrupt();
}

ISR(TIMER1_OVF_vect) {  
  if(phaseShift < 0) handleT1Interrupt();
}

void handleT1Interrupt() {
  TCNT2 = 0; // Сброс счетчика Timer2
  OCR2A = ocr2_start;
  TCCR2B = prescaler2_start; // Запуск Timer2
  TIMSK2 |= (1 << OCIE2A); // Разрешение прерывания
}

ISR(TIMER2_COMPA_vect) {
  if(!isT2Active) {
    digitalWrite(pinT2, HIGH); // Начало импульса
    OCR2A = ocr2_pulse;
    TCCR2B = prescaler2_pulse; // Установка длительности
    isT2Active = true;
  } else {
    digitalWrite(pinT2, LOW); // Конец импульса
    TCCR2B = 0; // Остановка Timer2
    TIMSK2 &= ~(1 << OCIE2A);
    isT2Active = false;
  }
}

/*==============================================================================
  LOOP SECTION 
==============================================================================*/

void loop() {

}
Код из блока Flprog компилируется но не работает нет сигналов..

Код: Выделить всё

#include "flprogUtilites.h"
#include <avr/interrupt.h>
float Per_193484155_1;
float pulseT1_193484155_1;
float pulseT2_193484155_1;
float phaseShift_193484155_1;
const float MIN_FREQ_193484155_1= 0.2; // ~0.2 Гц (период ~5 сек)
const float MAX_FREQ_193484155_1= 1000.0; // 1 кГц (период 1 мс)
volatile bool isT2Active_193484155_1= false;
volatile uint16_t icr1_value, ocr1_value, ocr2_start, ocr2_pulse_193484155_1;
volatile uint8_t prescaler1, prescaler2_start, prescaler2_pulse_193484155_1;
int use_OC1A_193484155_1= false;
int use_OC2A_193484155_1= false;
bool validateParameters_193484155_1();
void configureTimers_193484155_1();
void setTimer1Prescaler_193484155_1(float period_us);
void setTimer1Registers_193484155_1();
uint16_t calculateTimer2_193484155_1(float ms, uint8_t* prescaler);
void handleT1Interrupt_193484155_1();
uint16_t scalerValueTimer1_193484155_1(uint8_t prescaler);
void updateParameters_193484155_1(float newPer, float newPulseT1, float newPulseT2, float newPhaseShift);
void updatePer_193484155_1(float newPer);
void updatePulses_193484155_1(float newPulseT1, float newPulseT2);
void updatePhaseShift_193484155_1(float newPhaseShift);
void setup()
{
    // Проверка параметров
    use_OC1A_193484155_1 = (9 == 9);
    use_OC2A_193484155_1 = (3 == 11);
    pinMode(9, OUTPUT);
    pinMode(3, OUTPUT);
    if (!validateParameters_193484155_1()) while(1); // Блокировка при ошибке
      configureTimers_193484155_1();
    sei(); // Разрешение прерываний
}
void loop()
{
    //Плата:1
    Per_193484155_1 = 50.00;
    pulseT1_193484155_1 = 2.5;
    pulseT2_193484155_1 = 10.2;
    phaseShift_193484155_1 = 1.3;
    // Основная логика нет, работа через прерывания
}
bool validateParameters_193484155_1()
{
    // ===== ПРОВЕРКА ПАРАМЕТРОВ =====
     float period_ms = 1000.0 / Per_193484155_1;
    return !((9 != 9 && 9 != 10) ||      (3 != 3 && 3 != 11) ||     (Per_193484155_1 < 0.2 || Per_193484155_1 > 1000.0) ||     // Диапазон частот
    (pulseT1_193484155_1 < 0.1 || pulseT2_193484155_1 < 0.1) || // Минимальная длительность
    (pulseT1_193484155_1 >= period_ms) ||           // T1 не должен заполнять весь период
    (pulseT1_193484155_1 + phaseShift_193484155_1 + pulseT2_193484155_1 >= period_ms) // Наложение сигналов
);
}
void configureTimers_193484155_1()
{
    // ===== КОНФИГУРАЦИЯ ТАЙМЕРОВ =====
     // Расчет периода (мкс)
     float period_us = 1e6 / Per_193484155_1;
    // Настройка Timer1
       TCCR1A = TCCR1B = 0;
    setTimer1Prescaler_193484155_1(period_us);
    setTimer1Registers_193484155_1();
    // Настройка Timer2
     TCCR2A = (use_OC2A_193484155_1) ? (1 << COM2A1) : (1 << COM2B1); // Режим сравнения
      TCCR2B = 0; // Предделитель пока выключен
    // Конфигурация Timer2
      float startTime = pulseT1_193484155_1 + phaseShift_193484155_1;
    phaseShift_193484155_1 >= -pulseT1_193484155_1;
    ocr2_start = calculateTimer2_193484155_1(fabs(startTime), &prescaler2_start);
    ocr2_pulse_193484155_1 = calculateTimer2_193484155_1(pulseT2_193484155_1, &prescaler2_pulse_193484155_1);
    // Разрешение прерываний
    TIMSK1 = (1 << TOIE1) | ((phaseShift_193484155_1 >= 0) ? (use_OC1A_193484155_1 ? (1 << OCIE1A) : (1 << OCIE1B)) : 0);
}
void setTimer1Prescaler_193484155_1(float period_us)
{
    const float scalers[] = {1.0, 8.0, 64.0, 256.0, 1024.0};
    for(int i = 4; i >= 0; i--) 
    {
        icr1_value = (period_us * 16.0 / scalers[i]) - 1;
        if(icr1_value <= 65535) 
        {
            prescaler1 = (i == 4) ? 0x05 : (i == 3) ? 0x04 :
            (i == 2) ? 0x03 : (i == 1) ? 0x02 : 0x01;
            return;
        }
    }
    icr1_value = 65535; // Максимальное значение при ошибке
}
void setTimer1Registers_193484155_1()
{
    TCCR1A = (1 << WGM11); // Fast PWM (ICR1)
      TCCR1B = (1 << WGM13) | (1 << WGM12) | prescaler1;
    // Расчет OCR1
      float ticks = (pulseT1_193484155_1 * 1000.0 * 16.0) / scalerValueTimer1_193484155_1(prescaler1);
    ocr1_value = constrain(ticks - 1, 1, icr1_value);
    // Настройка вывода
      TCCR1A &= ~((1 << COM1A1) | (1 << COM1B1));
    if(use_OC1A_193484155_1) 
    {
        TCCR1A |= (1 << COM1A1); // Неинверсный режим
            OCR1A = ocr1_value;
    }
     else 
    {
        TCCR1A |= (1 << COM1B1);
        OCR1B = ocr1_value;
    }
    ICR1 = icr1_value; // Установка периода
}
uint16_t calculateTimer2_193484155_1(float ms, uint8_t* prescaler)
{
    const float scalers[] = {1.0, 8.0, 32.0, 64.0, 128.0, 256.0};
    float target_ticks = ms * 1000.0 * 16.0;
    for(uint8_t i = 0; i < 6; i++) 
    {
        float val = target_ticks / scalers[i];
        if(val <= 256.0) 
        {
            *prescaler = (i == 0) ? 0x01 : (i == 1) ? 0x02 :
            (i == 2) ? 0x03 : (i == 3) ? 0x04 :
            (i == 4) ? 0x05 : 0x06;
            return val - 1;
        }
    }
    return 255; // Максимальное значение
}
uint16_t scalerValueTimer1_193484155_1(uint8_t prescaler)
{
     switch(prescaler) 
    {
        case 0x01: return 1;
        case 0x02: return 8;
        case 0x03: return 64;
        case 0x04: return 256;
        case 0x05: return 1024;
        default: return 1;
    }
}
void updateParameters_193484155_1(float newPer, float newPulseT1, float newPulseT2, float newPhaseShift)
{
    cli();
    float oldParams[4] = {Per_193484155_1, pulseT1_193484155_1, pulseT2_193484155_1, phaseShift_193484155_1};
    Per_193484155_1 = newPer;
    pulseT1_193484155_1 = newPulseT1;
    pulseT2_193484155_1 = newPulseT2;
    phaseShift_193484155_1 = newPhaseShift;
    if(!validateParameters_193484155_1()) 
    {
        // Откат при ошибке
            Per_193484155_1 = oldParams[0];
        pulseT1_193484155_1 = oldParams[1];
        pulseT2_193484155_1 = oldParams[2];
        phaseShift_193484155_1 = oldParams[3];
    }
     else 
    {
        configureTimers_193484155_1();
    }
    sei();
}
void updatePer_193484155_1(float newPer)
{
    float newPulseT1 = (pulseT1_193484155_1 * Per_193484155_1) / newPer; // Сохранение скважности
      updateParameters_193484155_1(newPer, newPulseT1, pulseT2_193484155_1, phaseShift_193484155_1);
}
void updatePulses_193484155_1(float newPulseT1, float newPulseT2)
{
     updateParameters_193484155_1(Per_193484155_1, newPulseT1, newPulseT2, phaseShift_193484155_1);
}
void updatePhaseShift_193484155_1(float newPhaseShift)
{
    cli();
    while(isT2Active_193484155_1); // Ожидание завершения импульса T2
      updateParameters_193484155_1(Per_193484155_1, pulseT1_193484155_1, pulseT2_193484155_1, newPhaseShift);
}
ISR(TIMER1_COMPA_vect)
{
    if(phaseShift_193484155_1 >= 0 && use_OC1A_193484155_1) handleT1Interrupt_193484155_1();
}
ISR(TIMER1_COMPB_vect)
{
    if(phaseShift_193484155_1 >= 0 && !use_OC1A_193484155_1) handleT1Interrupt_193484155_1();
}
ISR(TIMER1_OVF_vect)
{
    if(phaseShift_193484155_1 < 0) handleT1Interrupt_193484155_1();
}
void handleT1Interrupt_193484155_1()
{
    TCNT2 = 0; // Сброс счетчика Timer2
      OCR2A = ocr2_start;
    TCCR2B = prescaler2_start; // Запуск Timer2
      TIMSK2 |= (1 << OCIE2A); // Разрешение прерывания
}
ISR(TIMER2_COMPA_vect)
{
     if(!isT2Active_193484155_1) 
    {
        digitalWrite(3, HIGH); // Начало импульса
            OCR2A = ocr2_pulse_193484155_1;
        TCCR2B = prescaler2_pulse_193484155_1; // Установка длительности
            isT2Active_193484155_1 = true;
    }
     else 
    {
        digitalWrite(3, LOW); // Конец импульса
            TCCR2B = 0; // Остановка Timer2
            TIMSK2 &= ~(1 << OCIE2A);
        isT2Active_193484155_1 = false;
    }
}
У вас нет необходимых прав для просмотра вложений в этом сообщении.
ecoins
Полковник
Сообщения: 3999
Зарегистрирован: 12 фев 2016, 11:40
Откуда: Шатура
Имя: Энвер
Благодарил (а): 136 раз
Поблагодарили: 149 раз

Re: После создания блока FLprog код перестает работать

Сообщение ecoins »

VNL64T писал(а): 30 апр 2025, 12:48 Добрый день. написал код для управления Шим, самостоятельно через IDE работает прекрасно, решил создать блок и тут тупик Может кто подскажет? или свежи взгляд ,,, СПАСИБО

Рабочий код...
Вы проделали большую работу и скорее всего сделали все почти правильно.
И конечно требуется отладка.
Можно потратить усилия, но хотелось бы понять несколько это рационально.
1.Этот код ориентирован на AVR. Сейчас FLProg поддерживает это направление в случаях крайней необходимости.
Это действительно нужно? И эта работа может быть масштабирована для других пользователей.
2.В AVR имеется встроенный ШИМ и он также реализован на прерываниях от таймеров. При этом эти таймеры распределены между пинами для повышения частоты ШИМа. Что-то препятствует использование стандартной реализации?
3.При повышенных требованиях к ШИМ есть прекрасный модуль PCA9685 -16 ШИМ 16разрядов.
Это решение не удобно?
4.На ESP32 реализуется до 16 ШИМ до 24разрядов (в этих чипах много таймеров).
Такое решение Вам может подойти?
С уважением, ecoins.
VNL64T
Рядовой
Сообщения: 62
Зарегистрирован: 22 янв 2024, 05:37
Имя: Алекс
Благодарил (а): 2 раза
Поблагодарили: 6 раз

Re: После создания блока FLprog код перестает работать

Сообщение VNL64T »

ecoins писал(а): 30 апр 2025, 13:58
VNL64T писал(а): 30 апр 2025, 12:48 Добрый день. написал код для управления Шим, самостоятельно через IDE работает прекрасно, решил создать блок и тут тупик Может кто подскажет? или свежи взгляд ,,, СПАСИБО

Рабочий код...
Вы проделали большую работу и скорее всего сделали все почти правильно.
И конечно требуется отладка.
Можно потратить усилия, но хотелось бы понять несколько это рационально.
1.Этот код ориентирован на AVR. Сейчас FLProg поддерживает это направление в случаях крайней необходимости.
Это действительно нужно? И эта работа может быть масштабирована для других пользователей.
2.В AVR имеется встроенный ШИМ и он также реализован на прерываниях от таймеров. При этом эти таймеры распределены между пинами для повышения частоты ШИМа. Что-то препятствует использование стандартной реализации?
3.При повышенных требованиях к ШИМ есть прекрасный модуль PCA9685 -16 ШИМ 16разрядов.
Это решение не удобно?
4.На ESP32 реализуется до 16 ШИМ до 24разрядов (в этих чипах много таймеров).
Такое решение Вам может подойти?
С уважением, ecoins.
Задумка была создать блок для своей задачи, затем как водится пошло наращивание желаний, и то что сейчас видно в коде не все что я хотел осуществить но на каком-то моменте видимо запутался, попытка быстро разобраться в проблеме только усугубляла ситуацию приходилось отступать назад..
На сколько это надо? сложно сказать но если никто не будет пытаться рано или поздно чудесный проект закончит свое существование..
Конечно я в случае успешной реализации хотел опубликовать блок для аудитории. да и просто интересно в конце концов что можно сделать с НАНО
aidar_i
Полковник
Сообщения: 3357
Зарегистрирован: 24 дек 2016, 16:55
Откуда: Уфа
Имя: Айдар
Благодарил (а): 12 раз
Поблагодарили: 100 раз
Контактная информация:

Re: После создания блока FLprog код перестает работать

Сообщение aidar_i »

ecoins писал(а): 30 апр 2025, 13:58 .....
Это действительно нужно?
.....
С уважением, ecoins.
Нужно поддержать форумчанина в желании осуществить выбранный им проект, пусть и AVR, пусть и может не то. Запустив его он приобретет энтузиазм и уверенность и желание далее развиваться в нашей программе. Сужу по себе.
VNL64T писал(а): 30 апр 2025, 23:47

Добрый день. написал код для управления Шим, самостоятельно через IDE работает прекрасно, решил создать блок и тут тупик Может кто подскажет? или свежи взгляд ,,, СПАСИБО

Задумка была создать блок для своей задачи, затем как водится пошло наращивание желаний, и то что сейчас видно в коде не все что я хотел осуществить но на каком-то моменте видимо запутался, попытка быстро разобраться в проблеме только усугубляла ситуацию приходилось отступать назад..
На сколько это надо? сложно сказать но если никто не будет пытаться рано или поздно чудесный проект закончит свое существование..
Конечно я в случае успешной реализации хотел опубликовать блок для аудитории. да и просто интересно в конце концов что можно сделать с НАНО
Вот в версии 8.2.3
ШИМ фаза4.flp
У вас нет необходимых прав для просмотра вложений в этом сообщении.
VNL64T
Рядовой
Сообщения: 62
Зарегистрирован: 22 янв 2024, 05:37
Имя: Алекс
Благодарил (а): 2 раза
Поблагодарили: 6 раз

Re: После создания блока FLprog код перестает работать

Сообщение VNL64T »

Спасибо за поддержку, реально приятно..
Пришлось задумку немного отложить в сторону, вернуться от хотелок к реальной задаче, обязательно посмотрю предложенное вами исправление, иногда глаз замыливается и в лоб не видишь где допустил ошибку..
Еще раз спасибо!!
Ответить

Вернуться в «Помогите, а то я "нимагу"»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя