А ещё у ESP-IDF какие-то проблемы либо с документацией либо с фриртосом. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html
Решил я архитектуру немного попеределать, и оказалось так что мне нужно посылать Notify в таску из двух разны задач. После недолгого гугленья понял что это делается с помощью xTaskNotifyIndexed(). В доке ESP-IDF даже про это написано, но вот в коде её нет и VsCode её не видит.
В итоге пришлось нашлёпать костылей с велосипедами. Во время Notify мы должны передать
Для того чтобы передать -23.88°C сделаем следующую логику, которая будет всем понятна, но за которую люди в свитерах и с красными глазами готовы убивать:
1) умножим на 1000 чтобы получить 23880 мллицельсий.
2) добавим 100*1000 чтобы значение точно было больше 0
3) добавим биты с инфой:
7) вычитаем 100 и делим на 1000 если бит гооврит о том что к нам прилетела температура
на графике сверху как раз таска жёлтым цветом отчитывается о том что получила нотифаи о температуре из ntcTask и о померяном напряжении из ecTask.
Решил я архитектуру немного попеределать, и оказалось так что мне нужно посылать Notify в таску из двух разны задач. После недолгого гугленья понял что это делается с помощью xTaskNotifyIndexed(). В доке ESP-IDF даже про это написано, но вот в коде её нет и VsCode её не видит.
В итоге пришлось нашлёпать костылей с велосипедами. Во время Notify мы должны передать
uint32_t
, а это 4 раза по 8 бит. Поэтому в первом бите будем передавать тип, а в остальных 3х значение (до 16 миллионов).Для того чтобы передать -23.88°C сделаем следующую логику, которая будет всем понятна, но за которую люди в свитерах и с красными глазами готовы убивать:
1) умножим на 1000 чтобы получить 23880 мллицельсий.
2) добавим 100*1000 чтобы значение точно было больше 0
3) добавим биты с инфой:
0b00000001 << 24
4) передаём получившееся uint32_t x
5) получаем биты с инфой x >> 24
6) поучаем значение наложив маску7) вычитаем 100 и делим на 1000 если бит гооврит о том что к нам прилетела температура
на графике сверху как раз таска жёлтым цветом отчитывается о том что получила нотифаи о температуре из ntcTask и о померяном напряжении из ecTask.
This media is not supported in your browser
VIEW IN TELEGRAM
Морс! Клюква!
Весь вечер делаю дооолгие замеры, чтобы процесс устоялся и при повторном измерении получалась та-же цифра что и первоначально.
Стабильность показаний и их повторяемость при перемещении между баночками в случайном порядке радуют - (2-3mV).
Если присмотреться - то видно что рядом с синим штекером EC щупа появился синий (СТИЛЬ!!!) джампер который воткнут в дальнюю от нас позицию. Это говорит о том что теперь на делителе напряжения сопротивление 500Ω вместо неправильных 4700Ω
Весь вечер делаю дооолгие замеры, чтобы процесс устоялся и при повторном измерении получалась та-же цифра что и первоначально.
Стабильность показаний и их повторяемость при перемещении между баночками в случайном порядке радуют - (2-3mV).
Если присмотреться - то видно что рядом с синим штекером EC щупа появился синий (СТИЛЬ!!!) джампер который воткнут в дальнюю от нас позицию. Это говорит о том что теперь на делителе напряжения сопротивление 500Ω вместо неправильных 4700Ω
График тоже получается красивый.
Когда я делал похожие измерения раньше - у меня всегда начинали уплывать показатели на значениях 5-6 EC. А тут даже в этих цифрах всё сходится.
Калибровочные коэффициенты, правда подобрал вручную: решение калибровочных уравнений осталось только в коде на C++, а на компе это запускать лень.
Когда я делал похожие измерения раньше - у меня всегда начинали уплывать показатели на значениях 5-6 EC. А тут даже в этих цифрах всё сходится.
Калибровочные коэффициенты, правда подобрал вручную: решение калибровочных уравнений осталось только в коде на C++, а на компе это запускать лень.
А вот так получается если коэффициенты подобрать решением математических уравнений.
Оказывается можно ничего не устанавливать, а пользоваться программой в которой я всё считал онлайн:
https://sagecell.sagemath.org/
Система уравнений на первый взгляд кажется очень простой:
Почему уравнения такие? ну хз так показалось 😂
Оказывается можно ничего не устанавливать, а пользоваться программой в которой я всё считал онлайн:
https://sagecell.sagemath.org/
Система уравнений на первый взгляд кажется очень простой:
a/(R1-b)-c==EC1Зная сопротивления (R) и электропроводимость (EC) нужно посчитать систему из 3х уравнений =)
a/(R2-b)-c==EC2
a/(R3-b)-c==EC3
Почему уравнения такие? ну хз так показалось 😂
Уравнения выглядят просто, а вот решение их устрашает)
Самому такое решение конечно вывести слишком долго и сложно.
Sagemath сделает это за вас - нужно просто все известные R и EC в формуле выше заменить на переменные.
Выглядит как реклама) продукт опенсорсный кстати =)
pow()
в коде - это возведение в степень, а остальные символы должны быть знакомы.Самому такое решение конечно вывести слишком долго и сложно.
Sagemath сделает это за вас - нужно просто все известные R и EC в формуле выше заменить на переменные.
Выглядит как реклама) продукт опенсорсный кстати =)
Решение в переменных для желающих повторить)
И ещё раз ссылка на онлайн:
https://sagecell.sagemath.org/
И ещё раз ссылка на онлайн:
https://sagecell.sagemath.org/
Закончим всё это двухдневным графиком с другой установки, которая будет жить долго.
График показывает что без температурной компенсации мы получаем термометр, а не ЕС/TDS метр.
Кстати цифрам сползания температуры верить нельзя. Там термометр совсем не калиброванный, с какими-то дикими коэффициентами для того чтобы это хоть как-то сходилось.
Насколько конкретно влияет температура на EC - смотрите в следующих сериях.
График показывает что без температурной компенсации мы получаем термометр, а не ЕС/TDS метр.
Кстати цифрам сползания температуры верить нельзя. Там термометр совсем не калиброванный, с какими-то дикими коэффициентами для того чтобы это хоть как-то сходилось.
Насколько конкретно влияет температура на EC - смотрите в следующих сериях.
IOT / Esp32 / FreeRTOS / Arduino / stm32
Но есть вещь которая смущает гораздо больше чем пара десятков милливольт выше. Иногда эта дельта улетает в космос и эти "улёты" вполне стабильны и статичны и точно зависят от каких-то вещей в прошивке. Одно радует что средние значения при этом не меняются.…
Перебрал весь проект, отрефакторил всё что смог, каждый кусочек каждой функции, и нашёл проблему!
Она конечно-же заключалась в отвалившемся источнике опорного, который я самостоятельно припаял на плату.
Она конечно-же заключалась в отвалившемся источнике опорного, который я самостоятельно припаял на плату.
This media is not supported in your browser
VIEW IN TELEGRAM
Периоды работы и неработы. Количество циклов и размер оверсемплинга выставлены в небольшое значение, потому что так проще тестировать.
Можно ещё немного подшаманить, убрав лишние выключения, но похоже что 8.3kHz в данном случае это предел. Будет интересно сравнить это с результатами на stm32, когда приедет платка.
Возможно частоту можно увеличить, если писать напрямую в регистры и использовать DMA для ацп, но на данном этапе не вижу смысла в это упарываться.
Возможно частоту можно увеличить, если писать напрямую в регистры и использовать DMA для ацп, но на данном этапе не вижу смысла в это упарываться.
Очень много одинаковых картинок с осцилографа)
Но стоит ещё написать про оверсемплинг, потому что это важно.
Итак я измеряю напряжение много раз и суммирую его в переменную.
Оверсемплинг - это когда мы много раз померяли, потом поделили на количество измерений, чтобы получить среднее.
Если эти действия делать кратными степени двойки, то вместо деления можно просто сделать побитовый сдвиг на рарзмер степени, что очень красиво и богоугодно.
Итак я использую по умолчанию степень 8, и получаю 2^8=256 измерений.
Всё что находится внутри этих измерений обернуто мьютексом, т.е. фриртосу сказано что это очень важный процесс, и не смей влезать сюда со своими другими задачами.
Вводную часть рассказал, теперь посмотрим на картинку:
- ширина клеточки 5ms
- ширина расколбаса ~6 клеточек или 30ms
- внутри должно быть 256 измерений
- делим 30/256 = 0,117ms на кажый цикл
И, о боже! 🥳 это число совпадает с длинной цикла на предыдущих картинках.
Максимум при которой система ещё работает - это 2^8=2048 внутри мьютекса.
Но стоит ещё написать про оверсемплинг, потому что это важно.
Итак я измеряю напряжение много раз и суммирую его в переменную.
Оверсемплинг - это когда мы много раз померяли, потом поделили на количество измерений, чтобы получить среднее.
Если эти действия делать кратными степени двойки, то вместо деления можно просто сделать побитовый сдвиг на рарзмер степени, что очень красиво и богоугодно.
Итак я использую по умолчанию степень 8, и получаю 2^8=256 измерений.
Всё что находится внутри этих измерений обернуто мьютексом, т.е. фриртосу сказано что это очень важный процесс, и не смей влезать сюда со своими другими задачами.
Вводную часть рассказал, теперь посмотрим на картинку:
- ширина клеточки 5ms
- ширина расколбаса ~6 клеточек или 30ms
- внутри должно быть 256 измерений
- делим 30/256 = 0,117ms на кажый цикл
И, о боже! 🥳 это число совпадает с длинной цикла на предыдущих картинках.
Максимум при которой система ещё работает - это 2^8=2048 внутри мьютекса.