Добрый день, извините возможно за глупый вопрос, есть плата UNO R3, на A0 - приходит 0-5В, на цифровом 2 висит датчик холла, написал код чтобы данные с А0 и D2 раз в секунду записывались на SD-карту. Для проверки взял ESP32 и пустил с нее имитацию холла, и постоянный выход 2В, собрал все, но возникла проблема на А0 как я понял присутствует напряжение в простое без подключеной ESP, напряжение не постоянное а меняющееся с 2 до 4.2В При подключении ЕСП напряжение устанавливается в районе 3.442 - 3.447В но иногда появляется ноль. Мультиметром на выходе с ЕСП 32 я вижу 1.96. Данные с порта прикрепляю (слева с подключенной ЕСП, справа без).
Я начинающий в теме ардуино, скажу честно этот проект начал делать не я, у нас небольшая государственная техническая секция по картингу, в рамках применения компьютерных технологий, один из участников секции предложил сделать регистратор данных на ардуино, в его задачу входит получение аналогового сигнала 0-5В с контроллера лямбда-зонда и получение оборотов с датчика ХХ, все это записывать на СД-карту, для дальнейшего построения графика в Excel. Он начал реализовывать задачу, но в дальнейшем проект застопорился, и парень ушел с секции, я как тренер решил продолжить это.
С чем может быть связано такое поведение на аналоговом пине? нужны какие то фильтры?
Очевидно нет подтяжки входа. Вход очень чувствителен к любым возмущениям.
Сопротивлением 10-100 кОм вход притянуть к земле, дараллельно ёмкость керамическую 0.01-1 мкФ.
Данные раз в секунду, то есть статичные, постоянные, а ёмкость на всякий случай, вдруг рядом помеха пойдёт? Я бы поставил, хоть и не так это важно.
Хотя…непонятно что там источником 0-5в будет. Скорей всего вообще не надо ничего мудрить. Проблема-то при неподключеном входе.
И вообще, чем больше конденсаторов, тем ты круче в глазах неспециалистов😄
Емкость нужна. Причем, в гораздо большей степени, чем сопротивление.
Другое дело, пока не опубликована схема, все это не более, чем досужие размышления.
ТС, если задаешь вопрос, первое, что нужно сделать, - опубликовать скетч и схему.
возьми ADS1115, там 4-ре канала, получишь реальную картину, у ESP32 не важный ADC, измеряет от 0.1 вольта, для измерения больших напряжений до 2.5 вольта включается внутренний делитель
фнч по входу ацп всегда желателен, какую частоту среза ему задать это уже по задаче.
есть такая очевидность, не поставить заложенную в плату деталь проще, чем поставить не заложенную.
Для правильной работы ацп нужно учитывать выходное сопротивление источника - фнч - входное сопротивление ацп, т.к. резистор фнч образует с входным сопротивлением ацп делитель.
Резистор и конденсатор фнч следует устанавливать непосредственно на ноге ацп.
У нас есть датчик кислорода, к нему есть контроллер, который выводит показания с датчика на дисплей, но в контроллере нет функции записи лога, предусмотрен аналоговый выход 0-5В, где 0 это 10AFR (Air Fuel ratio) т.е бедная смесь, а 5 это 20AFR богатая смесь. Контроллер сделан на Open Source, к сожалению что и как в нем устроено я не могу сказать я не настолько продвинут в электронике, могу прикрепить архив с файлами для изготовления. К сожалению больше ничего сказать про него не могу.
#include <SPI.h>
#include <SD.h>
// Определяем пины для входов
const int analogPin = A0; // Пин для аналогового сигнала
const int digitalPin = 2; // Пин для цифрового сигнала
const int chipSelect = 10; // Пин выбора чипа для модуля SD
// Переменные для расчета RPM
volatile unsigned long lastflash = 0;
float RPM = 0;
File dataFile;
void setup() {
// Настраиваем скорость передачи данных для монитор порта
Serial.begin(9600);
// Устанавливаем режимы пинов
pinMode(digitalPin, INPUT); // Устанавливаем цифровой пин как вход
pinMode(chipSelect, OUTPUT); // Устанавливаем пин выбора чипа как выход
// Инициализируем значение последнего времени
lastflash = micros();
// Инициализация модуля SD
if (!SD.begin(chipSelect)) {
Serial.println("Ошибка инициализации SD");
return;
}
// Создание или открытие файла для записи
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
dataFile.println("Analog Voltage, RPM");
dataFile.close();
} else {
Serial.println("Ошибка открытия файла для записи");
}
}
void loop() {
// Читаем значение аналогового сигнала
int analogValue = analogRead(analogPin);
// Преобразуем значение аналогового сигнала в вольты
float voltage = analogValue * (5.0 / 1024.0);
// Читаем значение цифрового сигнала
int digitalValue = digitalRead(digitalPin);
// Если цифровой сигнал изменился, вызываем функцию sens()
if (digitalValue == HIGH && (micros() - lastflash) > 1000) { // Фильтр от дребезга контактов
sens(); // Вызов функции для расчета RPM
}
// Если прошло больше секунды с последнего импульса, считаем что RPM = 0
if ((micros() - lastflash) > 1000000) {
RPM = 0;
}
// Выводим значения в монитор порта
Serial.print("Analog Voltage: ");
Serial.print(voltage, 3); // Значение в вольтах с тремя знаками после запятой
Serial.print(" V RPM: ");
Serial.println(RPM);
// Открываем файл для записи данных
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
dataFile.print(voltage, 3);
dataFile.print(", ");
dataFile.println(RPM);
dataFile.close(); // Закрываем файл после записи
} else {
Serial.println("Ошибка записи в файл");
}
// Добавляем задержку, чтобы не перегружать монитор порта
delay(1000);
}
void sens() {
// Расчет RPM
RPM = 60.0 / ((float)(micros() - lastflash) / 1000000.0); // Расчет
lastflash = micros(); // Запомнить время последнего оборота
}
Смущает она что-то. Ещё и float.
60/(x/10000000)= 60000000/x.
Конечно, лучше бы на таймере измерять, ну да ладно, “Работает? Не трогай!”)
Либо не micros, а millis, либо значение micros сократить до uint16, точности должно хватить.
А то вычисления очень “тяжёлые”. @ЕвгенийП , хороший вопрос задам, сам сталкивался с необходимостью деления. Пытался как-то сократить вычисления(жёсткое ограничение времени было), но так и не обошёл деление. Есть ли способ вообще обойти его? Ну может там какие хитроумные битовые операции?
Эту часть взяли из готового примера тахометра у Алексгайвера если что, сам датчик холла еще не подключал, попробую в ближайшие пару дней подключить, и найти магнит для испытания. На простом тахометре оно работало, мы использовали его на нано.
В приведенном примере используется числа с плавающей точкой. В этом случае, естественно, деление на 1000000.0 элементарно заменяется умножением на 0.000001.
Для целых чисел можно умножить на 4295 и сдвинуть вправо. (либо подобрать другую пару множителя и величины сдвига в зависимости от требований к времени выполнения, точности и разрядности операндов).
Помнится, я заменял деление x/7 формулой x/8+x/64.
Плавающую точку можно вообще битово сдвигать? Странно, я об этом не думал и не проверял. И не помню можно ли сдвигать 4х байтное число или только 2х байтное. На досуге проверю разные варианты.
Какаха?))))
Да понял уже что нельзя. Мантисса, бит знака низя трогать скопом. Если только отдельно и со знанием, но зачем? Их надо всячески избегать. Видимо поэтому плохо с ними знаком- избегаю😄