Чтение данных с датчика MIS-3600-006DI

Попробую сменить интерфейс. Но я покупал чтобы был именно I2c.

#include <Wire.h>

#define SDA_PIN 8
#define SCL_PIN 9
#define PRESSURE_SENSOR_ADDRESS 0x76

uint16_t C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13;
bool calibrationLoaded = false;

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.setClock(100000);
  delay(100);
  
  loadCalibrationCoefficients();
  
  // Тестируем разные команды чтения
  testReadCommands();
}

void testReadCommands() {
  Serial.println("Тестирование команд чтения:");
  
  // Пробуем разные команды чтения
  byte readCommands[] = {0x60, 0x00, 0x01, 0x02, 0x03, 0x30, 0x31, 0x32, 0x33, 0x48, 0x49, 0x4A, 0x4B};
  
  for (int i = 0; i < sizeof(readCommands); i++) {
    testSingleCommand(readCommands[i]);
    delay(100);
  }
}

void testSingleCommand(byte cmd) {
  // Запускаем преобразование давления
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x49);  // D1 - давление
  Wire.endTransmission();
  delay(50);
  
  // Пробуем прочитать командой
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(cmd);
  byte error = Wire.endTransmission(false);
  
  if (error == 0) {
    Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
    if (Wire.available() >= 3) {
      uint8_t b1 = Wire.read();
      uint8_t b2 = Wire.read();
      uint8_t b3 = Wire.read();
      
      Serial.print("Команда 0x");
      if (cmd < 16) Serial.print("0");
      Serial.print(cmd, HEX);
      Serial.print(": ");
      Serial.print(b1, HEX);
      Serial.print(" ");
      Serial.print(b2, HEX);
      Serial.print(" ");
      Serial.print(b3, HEX);
      Serial.println();
    }
  }
}

void loadCalibrationCoefficients() {
  byte commands[13][2] = {
    {0x0E, 0x20}, {0x0E, 0x28}, {0x0E, 0x30}, {0x0E, 0x38},
    {0x0E, 0x40}, {0x0E, 0x48}, {0x0E, 0x50}, {0x0E, 0x58},
    {0x0E, 0x60}, {0x0E, 0x68}, {0x0E, 0x70}, {0x0E, 0x78},
    {0x0E, 0x80}
  };

  uint16_t* coefficients[] = {&C1, &C2, &C3, &C4, &C5, &C6, &C7, &C8, &C9, &C10, &C11, &C12, &C13};
  
  Serial.println("Загрузка коэффициентов...");
  
  for (int i = 0; i < 13; i++) {
    Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
    Wire.write(commands[i][0]);
    Wire.write(commands[i][1]);
    Wire.endTransmission();
    
    delay(10);
    
    Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 2);
    if (Wire.available() >= 2) {
      uint8_t msb = Wire.read();
      uint8_t lsb = Wire.read();
      *coefficients[i] = (msb << 8) | lsb;
    }
    delay(10);
  }
  calibrationLoaded = true;
  Serial.println("Коэффициенты загружены");
}

void loop() {
  // Основная функция чтения с наиболее вероятной командой
  readSensorData();
  delay(2000);
}

void readSensorData() {
  if (!calibrationLoaded) return;
  
  // Вариант 1: Попробуем команду 0x00 для чтения
  readWithCommand(0x00, "0x00");
  
  // Вариант 2: Или может быть команда 0x48
  // readWithCommand(0x48, "0x48");
}

void readWithCommand(byte readCmd, String cmdName) {
  // Запуск преобразования давления
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x49);  // D1 - давление
  Wire.endTransmission();
  delay(50);
  
  // Чтение давления
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(readCmd);
  Wire.endTransmission(false);
  
  Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
  if (Wire.available() >= 3) {
    uint8_t status = Wire.read();
    uint8_t msb_p = Wire.read();
    uint8_t lsb_p = Wire.read();
    uint32_t D1 = (msb_p << 8) | lsb_p;
    
    Serial.print(cmdName);
    Serial.print(" Давление: D1=");
    Serial.print(D1);
    Serial.print(" (0x");
    Serial.print(msb_p, HEX);
    Serial.print(lsb_p, HEX);
    Serial.print(") статус=0x");
    Serial.print(status, HEX);
    Serial.println();
  }
  
  delay(50);
  
  // Запуск преобразования температуры
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x21);  // D2 - температура
  Wire.endTransmission();
  delay(50);
  
  // Чтение температуры
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(readCmd);
  Wire.endTransmission(false);
  
  Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
  if (Wire.available() >= 3) {
    uint8_t status = Wire.read();
    uint8_t msb_t = Wire.read();
    uint8_t lsb_t = Wire.read();
    uint32_t D2 = (msb_t << 8) | lsb_t;
    
    Serial.print(cmdName);
    Serial.print(" Температура: D2=");
    Serial.print(D2);
    Serial.print(" (0x");
    Serial.print(msb_t, HEX);
    Serial.print(lsb_t, HEX);
    Serial.print(") статус=0x");
    Serial.print(status, HEX);
    Serial.println();
  }
}

если не помогло, значит не судьба))) хватит печатать, проверяйте код скорее!

1 лайк

Приветствую.
Согласно диаграмма reset это 0xAA & 0xAA.

Потом чтобы узнать какое количество байт, посчитал их в ответе, везде получилось по два байта.

09:44:28.170 → C1: <0E 20>: Bytes available: 0 | No data
09:44:29.188 → C2: <0E 28>: Bytes available: 0 | No data
09:44:29.188 → C3: <0E 30>: Bytes available: 2 | Data: 0x80 0x5C
09:44:29.224 → C4: <0E 38>: Bytes available: 0 | No data
09:44:30.233 → C5: <0E 40>: Bytes available: 0 | No data
09:44:30.233 → C6: <0E 48>: Bytes available: 0 | No data
09:44:31.260 → C7: <0E 50>: Bytes available: 0 | No data
09:44:31.260 → C8: <0E 58>: Bytes available: 0 | No data
09:44:32.277 → C9: <0E 60>: Bytes available: 0 | No data
09:44:32.277 → C10: <0E 68>: Bytes available: 2 | Data: 0x80 0x2B
09:44:32.277 → C11: <0E 70>: Bytes available: 2 | Data: 0x80 0x2A
09:44:32.319 → C12: <0E 78>: Bytes available: 2 | Data: 0x80 0xD6
09:44:32.319 → C13: <0E 80>: Bytes available: 0 | No data
09:44:33.374 → D2: <0F 21>: Bytes available: 2 | Data: 0x80 0x00
09:44:33.464 → D1: <0F 59>: Bytes available: 2 | Data: 0x80 0x00

Я в тупике )))

Честно сказать, даже не знаю что сказать )))
На всякий случай добавил Reset как в документации написано.

09:59:15.832 → Отправка команды RESET: <0xAA 0xAA>
09:59:15.959 → Загрузка коэффициентов…
09:59:29.245 → Коэффициенты загружены
09:59:29.245 → Тестирование команд чтения:
09:59:29.292 → Команда 0x60: 6A 68 7A
09:59:29.432 → Команда 0x00: 80 0 FF
09:59:29.573 → Команда 0x01: 80 0 FF
09:59:29.707 → Команда 0x02: 80 0 FF
09:59:29.882 → Команда 0x03: 80 0 FF
09:59:30.009 → Команда 0x30: 80 0 FF
09:59:30.192 → Команда 0x31: 80 0 FF
09:59:30.331 → Команда 0x32: 80 0 FF
09:59:30.462 → Команда 0x33: 80 0 FF
09:59:30.643 → Команда 0x48: 80 0 FF
09:59:30.768 → Команда 0x49: 80 0 FF
09:59:30.954 → Команда 0x4A: 80 0 FF
09:59:31.093 → Команда 0x4B: 80 0 FF
09:59:31.263 → 0x00 Давление: D1=255 (0x0FF) статус=0x80
09:59:31.341 → 0x00 Температура: D2=255 (0x0FF) статус=0x80
09:59:33.372 → 0x00 Давление: D1=255 (0x0FF) статус=0x80
09:59:33.497 → 0x00 Температура: D2=255 (0x0FF) статус=0x80
09:59:35.524 → 0x00 Давление: D1=255 (0x0FF) статус=0x80
09:59:35.653 → 0x00 Температура: D2=255 (0x0FF) статус=0x80
09:59:37.701 → 0x00 Давление: D1=255 (0x0FF) статус=0x80
09:59:37.793 → 0x00 Температура: D2=255 (0x0FF) статус=0x80
09:59:39.870 → 0x00 Давление: D1=255 (0x0FF) статус=0x80
09:59:39.962 → 0x00 Температура: D2=255 (0x0FF) статус=0x80
09:59:41.980 → 0x00 Давление: D1=255 (0x0FF) статус=0x80

это я не знаю что сказать))) не собирал, и не работал с этим датчиком
то что 0x60: 6A 68 7A прошло а остальные нет, это хорошо или плохо ?)))

Неправильно. См сообщение 24

Откуда вы их взяли? В ДШ такого не вижу

я и даташит, тем более когда не мне это надо, тем более бесплатно, вещи абсолютно не совместимые))) просто ыы скормил всю эту кашу…  по мере того как появляется инфа, меняется и ответ, если все равно не разобрался то может и поможет…вот еще код
#include <Wire.h>

#define SDA_PIN 8
#define SCL_PIN 9
#define PRESSURE_SENSOR_ADDRESS 0x76

uint16_t C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13;
bool calibrationLoaded = false;

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.setClock(100000);
  delay(100);
  
  // Правильный сброс
  resetSensor();
  delay(100);
  
  loadCalibrationCoefficients();
}

void resetSensor() {
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x1E);  // Правильная команда RESET
  Wire.endTransmission();
  delay(10);
}

void loadCalibrationCoefficients() {
  byte commands[13][2] = {
    {0x0E, 0x20}, {0x0E, 0x28}, {0x0E, 0x30}, {0x0E, 0x38},
    {0x0E, 0x40}, {0x0E, 0x48}, {0x0E, 0x50}, {0x0E, 0x58},
    {0x0E, 0x60}, {0x0E, 0x68}, {0x0E, 0x70}, {0x0E, 0x78},
    {0x0E, 0x80}
  };

  uint16_t* coefficients[] = {&C1, &C2, &C3, &C4, &C5, &C6, &C7, &C8, &C9, &C10, &C11, &C12, &C13};
  
  Serial.println("Загрузка коэффициентов...");
  
  for (int i = 0; i < 13; i++) {
    Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
    Wire.write(commands[i][0]);
    Wire.write(commands[i][1]);
    Wire.endTransmission();
    
    delay(10);
    
    // Читаем 3 байта вместо 2!
    Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
    if (Wire.available() >= 3) {
      uint8_t b1 = Wire.read();  // Статус
      uint8_t b2 = Wire.read();  // MSB
      uint8_t b3 = Wire.read();  // LSB
      
      *coefficients[i] = (b2 << 8) | b3;
      
      Serial.print("C");
      Serial.print(i+1);
      Serial.print(": 0x");
      if (b2 < 16) Serial.print("0");
      Serial.print(b2, HEX);
      if (b3 < 16) Serial.print("0");
      Serial.print(b3, HEX);
      Serial.print(" (статус: 0x");
      Serial.print(b1, HEX);
      Serial.println(")");
    } else {
      Serial.print("C");
      Serial.print(i+1);
      Serial.println(": No data");
    }
    delay(10);
  }
  calibrationLoaded = true;
  Serial.println("Коэффициенты загружены");
}

void loop() {
  readSensorData();
  delay(2000);
}

void readSensorData() {
  if (!calibrationLoaded) return;
  
  // Измерение давления
  uint32_t D1 = readPressure();
  
  // Измерение температуры
  uint32_t D2 = readTemperature();
  
  // Если данные валидные, вычисляем реальные значения
  if (D1 != 0 && D2 != 0) {
    calculateRealValues(D1, D2);
  }
}

uint32_t readPressure() {
  // Запуск преобразования давления
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x49);  // D1 - давление
  Wire.endTransmission();
  
  // Ждем завершения преобразования (увеличим задержку)
  delay(100);
  
  // Чтение результата
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x00);  // Команда чтения ADC
  Wire.endTransmission(false);
  
  Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
  if (Wire.available() >= 3) {
    uint8_t status = Wire.read();
    uint8_t msb = Wire.read();
    uint8_t lsb = Wire.read();
    
    Serial.print("D1 статус: 0x");
    Serial.print(status, HEX);
    Serial.print(" данные: 0x");
    Serial.print(msb, HEX);
    Serial.print(lsb, HEX);
    Serial.println();
    
    return (msb << 8) | lsb;
  }
  return 0;
}

uint32_t readTemperature() {
  // Запуск преобразования температуры
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x21);  // D2 - температура
  Wire.endTransmission();
  
  // Ждем завершения преобразования
  delay(100);
  
  // Чтение результата
  Wire.beginTransmission(PRESSURE_SENSOR_ADDRESS);
  Wire.write(0x00);  // Команда чтения ADC
  Wire.endTransmission(false);
  
  Wire.requestFrom(PRESSURE_SENSOR_ADDRESS, 3);
  if (Wire.available() >= 3) {
    uint8_t status = Wire.read();
    uint8_t msb = Wire.read();
    uint8_t lsb = Wire.read();
    
    Serial.print("D2 статус: 0x");
    Serial.print(status, HEX);
    Serial.print(" данные: 0x");
    Serial.print(msb, HEX);
    Serial.print(lsb, HEX);
    Serial.println();
    
    return (msb << 8) | lsb;
  }
  return 0;
}

void calculateRealValues(uint32_t D1, uint32_t D2) {
  // Здесь будет алгоритм вычисления реальных значений
  // на основе коэффициентов C1-C13 и данных D1, D2
  
  // Временный вывод сырых данных
  Serial.print("D1=");
  Serial.print(D1);
  Serial.print(" D2=");
  Serial.println(D2);
  
  // Простая проверка - если данные не 0x8000, то они вероятно валидны
  if (D1 != 0x8000 && D2 != 0x8000) {
    Serial.println("Данные выглядят валидными!");
  }
}

Ключевые исправления:

  1. Reset: 0x1E вместо 0xAA 0xAA

  2. Чтение коэффициентов: 3 байта вместо 2 (статус + данные)

  3. Увеличены задержки между командами

  4. Убраны лишние команды чтения (0x60 и др.)

  5. Правильная команда чтения ADC: 0x00

1 лайк

Такое я уже проходил.
Значения не меняются.

Загрузка коэффициентов…
C1: 0x687A (статус: 0x80)
C2: 0x00C8 (статус: 0x80)
C3: 0x5CB6 (статус: 0x80)
C4: 0x7D44 (статус: 0x80)
C5: 0x8667 (статус: 0x80)
C6: 0x8072 (статус: 0x80)
C7: 0x2F70 (статус: 0x80)
C8: 0x4A5F (статус: 0x80)
C9: 0xA079 (статус: 0x80)
C10: 0x2BB0 (статус: 0x80)
C11: 0x2AF8 (статус: 0x80)
C12: 0xD6D8 (статус: 0x80)
C13: 0x1F40 (статус: 0x80)
Коэффициенты загружены
D1 статус: 0x80 данные: 0x0FF
D2 статус: 0x80 данные: 0x0FF
D1=255 D2=255
Данные выглядят валидными!
D1 статус: 0x80 данные: 0x0FF
D2 статус: 0x80 данные: 0x0FF
D1=255 D2=255
Данные выглядят валидными!
D1 статус: 0x80 данные: 0x0FF
D2 статус: 0x80 данные: 0x0FF
D1=255 D2=255
Данные выглядят валидными!
D1 статус: 0x80 данные: 0x0FF

Семен-Семнныч… А я то думаю, откуда весь этот бред?

@127486
Слушайте, так все ваши вчерашние фантазии про какую-то команду 0x60 и про reset 0x1E- они тоже из ИИ?
Даташит САМИ не пробовали читать? Зачем вы мое время на ерунду тратите? Если начали спрашивать у ИИ - так пусть он вам и помогает. Требуйте, чтобы он исправил ошибки.

Покажи где кто-то просит вас тратить свое время! Это ваш личный выбор и предъявы по этому поводу раскидывать не стоит.

Что, реально всё из чатГпт?
Теперь мне понятно, откуда такое двойственное впечатление от вашего вопроса - вроде код показываете неплохой, грамотный - разве что с даташитом не совпадает.

Потому и код грамотный, что его ИИ писал. А сами вы, похоже, в нем ни строчки не понимаете.
Ладно, тогда удачи вам с ИИ и Babos

1 лайк

Интересно, что делать будете, когда/если ИИ прикалываться научится?))

тогда хотя бы легче будет отличить нормального новичка, который хочет научится. от такого как ТС

1 лайк

ну зайди сам на дипсик, он прикалывается, просто потом признается, да, было дело, накосячил, я его так достал, что он меня лесом послал )))

PS но он умеет вытаскивать скрытые ссылки на гитхабе, останется только договориться, чтобы дали доступ или ZIP прислали

Вообще авторы датчика те еще приколисты. Смотрим как они рекламируют свой датчик в начале даташита:


Выборочный перевод:

Внешний микропроцессор считывает необработанные выходные данные MIS-3600
и выполняет несложные преобразования в соответствии с коэффициентами,
хранящимися в памяти OTP. Таким образом, использование серии MIS-3600 позволяет
избавиться от утомительных калибровок и температурной компенсации.

А теперь посмотрим на эти “несложные преобразования” в апноте датчика:

Даташит начинается фразы “The MIS-3600 is an intelligent pressure sensor” :slight_smile: Если он такой умный - могли бы зашить свои “несложные преобразования” в прошивку, чтобы датчик выдавал по цифровому интерфейсу уже компенсированные значения.

Это не говоря о том, что датчик, например, требует подачи внешнего клока 32 КГц для работы АЦП, о чем в апноте нет ни слова.

5 лайков

так то и не работает видимо, ниже будет скетч в котором я с пяти пинков заставил ИИ написать генерацию PWM сигнала 32 килогерца высокой точности, главное это правильно его пинать и говорить **КАК НАДО ДЕЛАТЬ
**

#include <Wire.h>

// Адрес датчика MIS-3600-006DI по I2C (уточните в документации)
#define SENSOR_ADDRESS 0x28

// Пин для генерации 32 кГц
#define OUTPUT_PIN 9

// Регистры датчика (уточните в документации производителя)
#define STATUS_REG 0x00
#define DATA_MSB_REG 0x01
#define DATA_LSB_REG 0x02
#define CONFIG_REG 0x03

// Настройки таймера для 32 кГц
void setupTimer1() {
  // Останавливаем таймер
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // Режим CTC (сброс при совпадении)
  TCCR1B |= (1 << WGM12);

  // Делитель 1 (без предделителя)
  TCCR1B |= (1 << CS10);

  // Установка значения сравнения для 32 кГц
  // Частота тактирования Arduino 16 МГц
  // OCR1A = (F_CPU / (2 * N * Fout)) - 1
  // Где N = 1 (делитель), Fout = 32000 Гц
  OCR1A = (16000000L / (2 * 1 * 32000L)) - 1;

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

// Обработчик прерывания таймера
ISR(TIMER1_COMPA_vect) {
  digitalWrite(OUTPUT_PIN, digitalRead(OUTPUT_PIN) ^ 1);  // Переключение состояния пина
}

void setup() {
  // Инициализация последовательного порта
  Serial.begin(9600);

  // Инициализация I2C
  Wire.begin();

  // Настройка пина D9 как выход
  pinMode(OUTPUT_PIN, OUTPUT);

  // Настройка таймера для генерации 32 кГц
  //setupTimer1();
  //setupTimer1Precise();
  //setupTimer1_32kHz();
  setupTimer1_32KHz();
  //setupTimer1_32kHz_simple();

  // Инициализация датчика
  initializeSensor();

  Serial.println("Система инициализирована");
  Serial.println("Генерация 32 кГц на пине D9");
}

void initializeSensor() {
  // Конфигурация датчика (уточните настройки в документации)
  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(CONFIG_REG);
  Wire.write(0x01);  // Пример конфигурации - активация измерений
  Wire.endTransmission();

  delay(10);  // Небольшая задержка для инициализации
}

uint16_t readSensorData() {
  uint16_t data = 0;

  // Чтение данных из датчика
  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(DATA_MSB_REG);     // Указать регистр для чтения
  Wire.endTransmission(false);  // Повторный старт

  // Запрос 2 байт данных
  Wire.requestFrom(SENSOR_ADDRESS, 2);

  if (Wire.available() >= 2) {
    uint8_t msb = Wire.read();
    uint8_t lsb = Wire.read();
    data = (msb << 8) | lsb;
  }

  return data;
}

void loop() {
  // Чтение данных с датчика
  uint16_t sensorData = readSensorData();

  // Вывод данных в Serial Monitor
  Serial.print("Данные датчика: ");
  Serial.println(sensorData);

  // Проверка статуса датчика
  checkSensorStatus();

  delay(1000);  // Задержка 1 секунда между измерениями
}

void checkSensorStatus() {
  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(STATUS_REG);
  Wire.endTransmission(false);

  Wire.requestFrom(SENSOR_ADDRESS, 1);

  if (Wire.available()) {
    uint8_t status = Wire.read();

    if (status & 0x01) {
      Serial.println("Датчик готов");
    } else {
      Serial.println("Датчик не готов");
    }

    if (status & 0x02) {
      Serial.println("Ошибка данных");
    }
  }
}

// Альтернативная настройка для более точной частоты
void setupTimer1Precise() {
  noInterrupts();  // Отключить все прерывания

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // Режим CTC
  TCCR1B |= (1 << WGM12);

  // Делитель 1
  TCCR1B |= (1 << CS10);

  // Более точное значение для 32 кГц
  OCR1A = 249;  // (16000000 / (2 * 32000)) - 1 = 249

  TIMSK1 |= (1 << OCIE1A);

  interrupts();  // Включить прерывания
}

// Настройка таймера 1 для 32 кГц с Phase Correct PWM
void setupTimer1_32kHz() {
  // Отключить прерывания
  cli();

  // Сброс регистров
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // Настройка для Phase Correct PWM Mode 14 (10-bit)
  // WGM13:0 = 14 (1110) - Phase and Frequency Correct PWM
  TCCR1A |= (1 << WGM11) | (0 << WGM10);
  TCCR1B |= (1 << WGM13) | (0 << WGM12);

  // Предделитель для 32 кГц (для 16 МГц тактовой)
  TCCR1B |= (1 << CS10);  // Без предделителя

  // Установка частоты ~32 кГц
  ICR1 = (F_CPU / (2 * 32000)) - 1;  // TOP значение

  // Настройка канала A для PWM
  TCCR1A |= (1 << COM1A1);  // Non-inverting mode
  OCR1A = ICR1 / 2;         // 50% скважность

  // Включить прерывания
  sei();
}

void setupTimer1_32KHz() {
  // Отключить прерывания
  cli();
  
  // Сброс регистров
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  
  // Настройка для Fast PWM Mode 14 (ICR1 как TOP)
  // WGM13:0 = 14 (1110) - Fast PWM с ICR1
  TCCR1A |= (1 << WGM11) | (0 << WGM10);
  TCCR1B |= (1 << WGM13) | (1 << WGM12);
  
  // Без предделителя (CS12:0 = 001)
  TCCR1B |= (1 << CS10);
  
  // Установка частоты ~32 кГц для 16 МГц
  ICR1 = (16000000 / 32000) - 1; // TOP значение = 499
  
  // Настройка выхода на канале A (pin 9 на Arduino Uno)
  TCCR1A |= (1 << COM1A1); // Non-inverting mode
  
  // Установка скважности 50%
  OCR1A = ICR1 / 2; // 250
  
  // Включить прерывания
  sei();
  
  // Настроить пин как выход
  DDRB |= (1 << PB1); // PB1 (Arduino pin 9) как выход
}

void setupTimer1_32kHz_simple() {
  cli();

  // Сброс регистров
  TCCR1A = 0;
  TCCR1B = 0;

  // Fast PWM Mode 14, non-inverting
  TCCR1A = (1 << COM1A1) | (1 << WGM11);
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);

  // Частота 32 кГц
  ICR1 = 499;   // TOP = (16MHz / 32kHz) - 1 = 499
  OCR1A = 250;  // 50% скважность

  // Настроить пин как выход
  DDRB |= (1 << PB1);  // Arduino pin 9

  sei();
}

А ещё ГЛАВНЕЕ читать ТЗ! У ТС ESP! :grinning_face:

1 лайк

не просто ESP, а ESP32S3, а там надо смотреть какое ядро, делается по разному и о точности этой PWM ничего сказать не могу, а тут я асилограф включал и смотрел, ты думаешь я ИИ без асилографа и циркулярки пинал, как жеж, жди

ЗЫ не жалко и на ESP32S3, под аддон что у меня

#include "driver/ledc.h"

#define LEDC_OUTPUT_IO 5
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_TIMER LEDC_TIMER_0

void setup() {
  Serial.begin(115200);
  
  // Быстрая настройка
  ledc_timer_config_t timer_config = {
      .speed_mode = LEDC_LOW_SPEED_MODE,
      .duty_resolution = LEDC_TIMER_8_BIT,
      .timer_num = LEDC_TIMER,
      .freq_hz = 32000, // 32 кГц
      .clk_cfg = LEDC_AUTO_CLK
  };
  ledc_timer_config(&timer_config);

  ledc_channel_config_t channel_config = {
      .gpio_num = LEDC_OUTPUT_IO,
      .speed_mode = LEDC_LOW_SPEED_MODE,
      .channel = LEDC_CHANNEL,
      .timer_sel = LEDC_TIMER,
      .duty = 128 // 50%
  };
  ledc_channel_config(&channel_config);

  Serial.println("32 kHz PWM active on GPIO5");
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL, 128);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL);
}

void loop() {}

Он уже умеет :slight_smile: