Отрабатывался алгоритм определения длительности сигнала (например, получаемого при измерении концентрации углекислоты в воздухе). Для проверки использовалась плата ESP32 DevKitC V4 с процессором ESP32-D0WD-V3 (revision v3.1). Выводящий и приемный пины соединялись на прямую. Квадратный сигнал создавался традиционно High delayMicros Low delayMicros в одном из ядер процессора, прием с заданной частотой осуществлялся в другом ядре процессора так: пропуск “1”, пропуск “0”, включение счетчика, пропуск “1”, остановка счетчика. Созданы две программки, одно простые digital, вторая при прямой работе с пинами (DirectIo.h). Результаты абсолютно одинаковы. Полупериоды от 10000 мкс до 0 мкс определяются в целом верно. Наблюдаются отклонения 1-2 мкс.
Но полупериод 1000 мкс определяется неприемлемо. Получаются значения от 950 до 2002 мкс. Причина этого совершенно не понятна.
Очень беспокоюсь о твоем здоровье. Вопросы есть у тебя, а не у меня. Это тебе нужно получить на них ответы, а не мне.
Для ответов НЕОБХОДИМО размещать код. Не “похожий” и не намеками, а ровно тот, который загружен в контроллер. Никто не планирует тратить свою жизнь на то, чтобы “понять” что-то в твоем посте. И я в том числе. Разместишь код - кто-то, может и я, заметит ошибку и поможет тебе.
Код. По правилам форума, ТОЧНОЕ название контроллера, версия среды, версия ядра для ЕСП32… может быть еще что-то потом спросят, когда необходимое будет выполнено. Обычно еще и схема нужна, так как новички часто даже при подключении проводочков к кнопке дичь делают.
определитель длительности ВЫСОКОГО
Нужна развязка 4.7ком при работе с сигралом 5в
как завышение так и уменьшение, что странно
Длительность 2000 мкс определяется с точностью 2 мкс
Длительность 1500 мкс определяется с разбросом от 600 до 2000 мкс ??!!
При работе с digitalwrite без Directio.h также возниикают расхожждения
между задаваемой ддлительностью и определяемой. Примерно такие же как и с Directio
pic=10000 pp=9998/10002
pic= 1000 PP= 999 958 987 1983
pic= 100 PP= 99 101
pic= 10 PP= 9 11
pic= 2 PP= 1 3
pic= 1 pp= 2
pic= 0 PP= 1 иногда редко 6
*/
#include <DirectIO.h>
OutputPin pin(26);
Input<27> my_input;
unsigned long last_m=millis(),tt, pp, tt2, pic=1; // pic длительность высокого в микросек
int period=5000;
bool value;
TaskHandle_t One_task;
TaskHandle_t Two_task;
#define ONE_STACK_SIZE 30000
#define TWO_STACK_SIZE 30000
void setup() {
Serial.begin(115200);
delay(5000);
Serial.print("pic= ");Serial.println(pic);
disableCore0WDT(); // Блокировка прерываний
disableCore1WDT();
disableLoopWDT(); // You forgot this one !
//создаем задачу, которая будет выполняться на ядре 0 с максимальным приоритетом (1)
xTaskCreatePinnedToCore(
Task1code, /* Функция задачи. */
"One_Task", /* Ее имя. */
10000, /* Размер стека функции */
NULL, /* Параметры */
5, /* Приоритет */
&One_task, /* Дескриптор задачи для отслеживания */
0); /* Указываем пин для данного ядра */
delay(500);
//Создаем задачу, которая будет выполняться на ядре 1 с наивысшим приоритетом (1)
xTaskCreatePinnedToCore(
Task2code, /* Функция задачи. */
"Two_Task", /* Имя задачи. */
10000, /* Размер стека */
NULL, /* Параметры задачи */
1, /* Приоритет */
&Two_task, /* Дескриптор задачи для отслеживания */
1); /* Указываем пин для этой задачи */
delay(500);
}
//Task1code:Создает сигнал из 0 и 1 pic управляет длительностями 0 и 1
void Task1code( void * pvParameters )
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
pin = HIGH;
delayMicroseconds(pic);
pin = LOW;
delayMicroseconds(pic);
}
}
//Task2code: определяет длительность '1'
void Task2code( void * pvParameters )
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
if(millis()-last_m> period)
{
last_m=millis();
while(my_input == HIGH){} // Пропускаем окончание '1'
while(my_input == LOW){} // Затем надо дождаться '1', пропустив '0'
tt = micros(); // Начало '1'. На время выполнения этой команды результат уменьшается
while(my_input == HIGH){} // Ожидаем конца '1'.
pp = micros() - tt; // Определяем длину '1'. На время выполнения этой команды результат увеличивается
Serial.print("PP= ");Serial.println(pp);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
}
У меня библиотека по предыдущей ссылке работает с ESP32.
Кроме того все проблемы поименованные в первом тексте наблюдаются и при работе без привлечения DirectIO. Скетч прилагается
/*
определитель длительности ВЫСОКОГО
Нужна развязка 4.7ком при работе с сигралом 5в
При работе с digitalwrite возниикают расхожждения между задаваемой ддлительностью и определяемой
как завышение так и уменьшение, что странно
pic=10000 PP= 10001
pic=1000 PP= 2002 !! независимо от частоты измерения. Это таймеры!!
pic=500 PP= 501
pic=100 PP= 101
pic=50 PP= 51
pic=10 PP= 10/11
pic=5 PP= 5/6 5- редко
pic=2 PP= 2/3
pic=1 PP= 1/2 1 - редко
without pic pp=1
*/
#define Pin 27 //
#define Pin2 26 //
unsigned long tt, pp, tt2, pic=5; // pic длительность высокого в микросек
TaskHandle_t One_task;
TaskHandle_t Two_task;
#define ONE_STACK_SIZE 40000 // 4 Кб
#define TWO_STACK_SIZE 30000 // 30 Кб
void setup() {
// put your setup code here, to run once:
pinMode(Pin, INPUT_PULLDOWN);//, INPUT_PULLUP);INPUT_PULLDOWN);
pinMode(Pin2, OUTPUT);
Serial.begin(115200);
delay(5000);
Serial.print("pic= ");Serial.println(pic);
disableCore0WDT(); // Блокировка прерываний
disableCore1WDT();
disableLoopWDT(); // You forgot this one !
//создаем задачу, которая будет выполняться на ядре 0 с максимальным приоритетом (1)
xTaskCreatePinnedToCore(
Task1code, /* Функция задачи. */
"One_Task", /* Ее имя. */
10000, /* Размер стека функции */
NULL, /* Параметры */
5, /* Приоритет */
&One_task, /* Дескриптор задачи для отслеживания */
0); /* Указываем пин для данного ядра */
delay(500);
//Создаем задачу, которая будет выполняться на ядре 1 с наивысшим приоритетом (1)
xTaskCreatePinnedToCore(
Task2code, /* Функция задачи. */
"Two_Task", /* Имя задачи. */
10000, /* Размер стека */
NULL, /* Параметры задачи */
1, /* Приоритет */
&Two_task, /* Дескриптор задачи для отслеживания */
1); /* Указываем пин для этой задачи */
delay(500);
}
//Task1code: мигает светодиодом
void Task1code( void * pvParameters )
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
digitalWrite(Pin2,HIGH);
delayMicroseconds(pic);
digitalWrite(Pin2,LOW);
delayMicroseconds(pic);
}
}
//Task2code: отслеживает длительность высокого
void Task2code( void * pvParameters )
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;)
{
while(digitalRead(Pin) == HIGH){} // Ожидаем конец высокого
while(digitalRead(Pin) == LOW){} // Затем надо дождаться высокого
tt = micros(); // Начало высокого
while(digitalRead(Pin) == HIGH){} // Ожидаем конца высокого
pp = micros() - tt; // Определяем длину цуга
Serial.print("PP= ");Serial.println(pp);
delay(2000);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Прости, я не вникал подробно. Но в глаза бросается неаккуратность. Поясню: неаккуратность приводит читателя к мысли о общей неправильности, уж прости.
Итак про неаккуратность:
Нахрена стек 10000?
Нахрена дескрипторы, если в Ардуино они не поддерживаются?
Это не влияет на описанный тобой эффект, но просто выглядит странно.
Вы правы, если бы программа составлялась сама по себе. Здесь же для скорости была взята большая двух-ядерная программа пригодной структуры, из нее выкинута начинка и вставлена новая из элементов интернетовских примеров, соответствующих поставленной задаче.
Второй ваш результат практически совпал с моим. Что касается первого, то надо бы просчитать с другими исходными, например большими 1000. Возможно добавка к ожидаемому результату будет постоянная. А что касается ES32? то я использую двух-ядерную плату для устранения влияния всех используемых задержек, которые могли бы искажать результаты.