Сравнение скорости работы двух ардуинок

plotter1

✩✩✩✩✩✩✩
24 Ноя 2021
20
1
Сетап: две ардуины, соединины между собой проводом между ногами 3 и 2 с подтяжкой на массу через резистор 10кОм. Питаются от одного источника.

Столкнулся со странной ситуацией. Оцениваю скорость кварца одной ардуины на другой. Код на первой (передающей) ардуине:

C++:
#include <digitalWriteFast.h>
void setup() {
pinMode(3, OUTPUT);
digitalWriteFast(3, 0);
}

void loop() {
digitalWriteFast(3, 1);
delayMicroseconds(4);
digitalWriteFast(3, 0);
delay(1);
digitalWriteFast(3, 1);
delayMicroseconds(4);
digitalWriteFast(3, 0);
delay(9999999);
}
Дергаем лапкой на 4мкс, ждем некоторое время (тут 1мс), после чего дергаем второй раз и уходим в долгий сон.

код на принимающей ардуине:
C++:
volatile uint32_t tmr;
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
attachInterrupt(0, isr, RISING);
}
void isr() {
tmr = micros();
}
void loop() {
Serial.println(tmr);
delay(200);
}
Ждем когда прилетит единица, в прерывании записываем время в переменную, печатаем её в порт. Далее ждем когда прилетит вторая единица, пишем время в переменную и снова в порт.

И вот вся эта трахуёмина начинает работать только когда между передаваемыми единицами 1000мс и более. В принципе цель достигнута, разница в скорости кварцев обсчитана. Но вопрос, почему это не работает при паузе например 500мкс? Вернее работает, но наполовину: регистрируется только один импульс.
 

plotter1

✩✩✩✩✩✩✩
24 Ноя 2021
20
1
@Эдуард Анисимов, опыт программирования у меня примерно 2 недели :) Регистры я не уметь. Но та же фастрайт обещает менее 1мкс на выполнение (точнее: digitalWriteFast() port manipulation takes 125nS. ).
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,283
945
58
Марий-Эл
@plotter1, без разницы. Что бы обратится к этой функции, нужно поместить в стек её переменные и адрес возврата. Выполнить код, Забрать со стека адрес возврата. Вернуться обратно. Лишних телодвижений больше, чем рабочего кода. Обращение напрямую к регистрам уменьшит это время во много раз.
Когда нужны временнокритичные измерения, нужно работать с регистрами и узлами напрямую.
Может быть в Вашем коде есть ошибка. Я не знаю.
Я только знаю, что так не делается.
 

plotter1

✩✩✩✩✩✩✩
24 Ноя 2021
20
1
Допустим, что так. Но не целую же секунду это занимает.
 

poty

★★★★★★✩
19 Фев 2020
2,994
895
@plotter1, я вообще удивлён что это когда-либо работает. Вы сами-то не видите несоответствия таймингов?
Первая и вторая Ардуино несинхронизированы. Итак, для первой Ардуино отслеживаемый период состоит из "действие(длительность)":
1(125нс)=ждём(ок.8000нс)=0(125нс)=ждём(1000000нс)=1(125нс)=ждём(ок.8000нс)=0(125нс)=ждём(9999999000нс)
Во второй Ардуино период состоит из вывода в порт (примерно 500мкс на подготовку к выводу) и delay:
вывод(500000нс)=ждём(200000000нс)
А теперь представим, что прерывание от первой 1 в первой Ардуино произошло во второй Ардуино где-то в начале "ждём": в первой ардуино через чуть больше 1мс произойдёт второй приход 1, что вызовет прерывание во второй Ардуино и перезапишет переменную tmr, а мы всё ещё будем ждать начала вывода...
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,845
593
44
Далее ждем когда прилетит вторая единица, пишем время в переменную и снова в порт.
В это время пока данные все еще передаются в порт прилетает прерывание и ... ??? :)
Нужно использовать некую переменную или массив буфера, который потом и выводить.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
333
104
@Эдуард Анисимов,
>Что бы обратится к этой функции, нужно поместить в стек её переменные и адрес возврата.
Вы не правы. Там нет вызова функций, все на дефайнах, и в результате работает с портами напрямую. В этом и есть смысл <digitalWriteFast.h>
 

poty

★★★★★★✩
19 Фев 2020
2,994
895
@Bruzzer, я с этим полностью согласен, но сами интервалы задаются с помощью вызова нескольких функций, собственно, изощряться в одном месте, чтобы тут же наплодить ошибок в других местах...
Кроме того, очевидно, что прерывания будут влиять на результат как на приёмной, так и на передающей стороне.
 

bort707

★★★★★★✩
21 Сен 2020
2,904
863
И вот вся эта трахуёмина начинает работать только когда между передаваемыми единицами 1000мс и более. В принципе цель достигнута, разница в скорости кварцев обсчитана. Но вопрос, почему это не работает при паузе например 500мкс?
так все-таки - 1000 мс или мкс? - в исходном вопросе вы путаетесь...
 

Sergo_ST

★★★★★★✩
15 Мар 2020
822
747
Для таких вещей нужно использовать первый таймер в режиме захвата на приемной части, а на передающей задать шим сигнал любым таймером. Вопрос только зачем это всё?
 
  • Лойс +1
Реакции: poty

plotter1

✩✩✩✩✩✩✩
24 Ноя 2021
20
1
Поменьше токсичности!
Всем спасибо за пустой трёп и неконструктивную критику.
Пошевелив мозгом удалось допилить скетчи до приемлемого состояния. В результате получается вычислить разницу кварцев с точностью до микросекунды.
Вопрос только зачем это всё?
Для подгонки коррекции кварцев для проводных протоколов.
 

bort707

★★★★★★✩
21 Сен 2020
2,904
863
Для подгонки коррекции кварцев для проводных протоколов.
для каких же протоколов требуется такая точность? :)
Смайлик потому, что в любом протоколе имеется или несущая или тактовый сигнал, который позволяет приемнику подстроится к частоте передатчика в некоторых пределах без ювелирной подгонки кварцев:)
 
  • Лойс +1
Реакции: te238s, poty и Sergo_ST

poty

★★★★★★✩
19 Фев 2020
2,994
895
@Sergo_ST, да там не только это. Там много мест, которые заставляют усомниться в том, что даже 10мкс точности достижимы. Если только скетч не был полностью переписан, на что, судя по ответу, надеяться не приходится.
 
  • Лойс +1
Реакции: Sergo_ST

te238s

★★✩✩✩✩✩
14 Ноя 2021
375
94
Для УАРТ даже достаточно встроенного генератора,куда уж там кварц...да ещё и тщательно подобраный))) И не понятно
В результате получается вычислить разницу кварцев с точностью до микросекунды.
Я думал разница частот в Гц или процентах....
Имхо,Ардуино среда в принципе не предназначена для подобных задач. Максимум помигать,вывести на ЖКИ циферку и покрутить сервой. И это без мало-мальских требований по таймингам.