"Бортовой компьютер своими руками" или "Arduino для "чайника""

Автор Yaroslav, 16 Окт. 2017 в 19:30

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Yaroslav

Привет всем.
Вот зачесались у меня руки, захотелось разобраться с платформой Arduino. Поморгал диодами, покрутил серву, теперь решил попробовать сделать бортовой компьютер, который будет показывать напряжение, ток, скорость, считать мощность, потраченную энергию и т.д.

Цель проекта:
в первую очередь получить знания и  опыт работы с arduino;
во-вторых - получить работающий прибор для ежедневного использования.
в-третих - задокументировать процесс создания и собрать информацию которая пригодится другим таким же как я "чайникам" которые захотят повторить данный проект.

В сборке прибора планирую максимально использовать готовые платы, понимаю конечно что придется сделать небольшую схему для согласования сигналов и питания arduino, но вытравливать плату для голого микроконтроллера не буду, все должно быть максимально просто и повторяемо.

В процессе работы будет много вопросов, надеюсь более опытные коллеги мимо не пройдут и помогут-подскажут.
Строю лигерад

Yaroslav

#1
Первое что сделал, это схема для согласования напряжений к входам ардуино и питание.
Батарейное напряжение понижаем с помощью делителя и подаем на a0, у меня расчитано под 100в, так как батарею имею 22s li-po.
Сигнал с шунта контроллера усиливаем с помощью неинвертирующего усилителя на ОУ и отправляем на a1, пока расчет до 50а.
Питание - делитель напряжения и стабилизатор lm7805.

Вопросы:
1. Какой лучше использовать ОУ? На схеме нарисован lm358, выбран на угад как самый распространенный и дешевый но они продаются сдвоенными в одном корпусе, чем его заменить?
2. правильно я выбрал номиналы резисторов делителей, имею в виде не коэффициент а именно номиналы?
3. Может будут какие то еще замечания по схеме, возможно где то нужен конденсатор и т.д?
Строю лигерад

Dmitry__

Цитата: Yaroslav от 16 Окт. 2017 в 19:41
Вопросы:
1. Какой лучше использовать ОУ?
Ответ: никакой  :-)
Во-первых:
Цитата: Yaroslav от 16 Окт. 2017 в 19:30
В сборке прибора планирую максимально использовать готовые платы
Во-вторых, lm358 не ОУ Rail to Rail и с большим дрейфом. Это очень плохой усилитель для шунтов. Поэтому возвращаемся к пункту 1 и ставим готовую плату :)
http://roboparts.ru/products/acs712-30a
Есть такой датчик на 100 ампер.
Еще лучше с цифровым выходом (нужен внешний шунт):
http://roboparts.ru/products/cjmcu-226-ina226
Еще можно приспособить платы для квадрокоптеров: токовый шунт и датчик напряжения.

Цитировать2. правильно я выбрал номиналы резисторов делителей, имею в виде не коэффициент а именно номиналы.

Правильно, но смотреть на них сейчас нет смысла, т.к. они меняются без изменения платы. Единственное, я бы добавил конденсатор на нижний резистор. Аналоговые входы у дуины без буферизации и довольно низкоомные для АЦП (большое потребление в момент замера).
Цитировать3. Может будут какие то еще замечания по схеме, возможно где то нужен конденсатор и т.д?
Искать готовые датчики до последнего, никаких лазерно-утюжной технологии (ЛУТ)...



mr.Dream

я лм 358 успешно использовал с коэфициентом усиления 200. Сделал смещение нуля через подстроечник. Касательно низкоомности - где то в даташите вычитал про 100мОм.

скорость меряйте в прерываниях по периоду между импульсами - так проще и правильней. Я использовал PCINT для чтения трех датчиков холла и в прерываниях обновлял регистры, а в основной программе делал калькуляцию всего с переводом в обороты/скорость.

И еще, на ОУ нужно заводить дифференциальный сигнал с шунта, а не использовать общий минус, иначе будет мерить еще и падение на проводке :)

дисплей рекомендовал бы подключать не через параллельный интерфейс, а например через i2c. Четыре провода: два данных и два питания.

думаю, для показометра точности больше 10бит не нужно. мне было достаточно. а если нужно больше, можно использовать внешний ацп, например ads1115, он имеет настраиваемій коєфициент усиления + диф. усилитель в одном флаконе, 15бит в одну сторону, если не мерить отрицательное напряжение. но можно же и ток зарядки мерить тоже :)

Dmitry__

Цитата: mr.Dream от 16 Окт. 2017 в 20:37
я лм 358 успешно использовал с коэфициентом усиления 200
Это будет не сенсор тока, это будет показометр.
Цитата: mr.Dream от 16 Окт. 2017 в 20:37
Касательно низкоомности - где то в даташите вычитал про 100мОм.
Низкоомность  динамическая, у avr измерение ацп делается подключением конденсатора 14пф ко входу через резистор 1кOm. Это расписано в пдф. Без внешнего конденсатора будет ошибка плюс страшные перекрестные помехи при переключении каналов ацп.



Из пдф:
ЦитироватьThe ADC is optimized for analog signals with an output impedance of approximately 10 k or
less. If such a source is used, the sampling time will be negligible. If a source with higher imped-
ance is used, the sampling time will depend on how long time the source needs to charge the
S/H capacitor, with can vary widely. The user is recommended to only use low impedant sources
with slowly varying signals, since this minimizes the required charge transfer to the S/H
capacitor.


mr.Dream

[user]Dmitry__[/user], почему показометр? Сравнивал с ваттметром турниги, линейность присутствует, а малые токи не мерил им. Зато доступно)

А 14 пф и 1 ком это скорее всего паразитная ёмкость ключей мультиплексора. Если переключить канал и подождать пару миллисекунд все стабилизируется.) а высокой частоты переключения не нужно, и постоянная времени маленькая. Но лично я ставил конденсптор для фильтрации шума от шим и т.д.

Dmitry__

Цитата: mr.Dream от 16 Окт. 2017 в 21:24
[user]Dmitry__[/user], почему показометр? Сравнивал с ваттметром турниги, линейность присутствует, а малые токи не мерил им. Зато доступно)
У lm358 температурный дрейф больше измеряемого напряжения на шунте.  И он не "rail to rail", а смещать в рамки ОУ резистором - моветон, ведь смещение делается не от прецизионного Vref. Долго рассказывать теорию шунтов, первая нагугленная ссылка по "lm358 токовый шунт"
http://vrtp.ru/index.php?showtopic=17174
Цитата: mr.Dream от 16 Окт. 2017 в 21:24
А 14 пф и 1 ком это скорее всего паразитная ёмкость ключей мультиплексора.
Нет, это такое УВХ (устройство выбора хранения). И я привел цитату из пдф: Входное сопротивление должно быть меньше 10кОм.


Yaroslav

Цитата: Dmitry__ от 16 Окт. 2017 в 20:23
Еще лучше с цифровым выходом (нужен внешний шунт):
http://roboparts.ru/products/cjmcu-226-ina226
Очень интересный вариант, только наверное возьму INA219, их можно у нас найти а INA226 только с китая ждать.
В INA219 контакты измерения напряжения и тока совмещенные, наверное им буду только ток измерять, хочу подключить к шунту инфинеона через разъем для CA.
Цитата: Dmitry__ от 16 Окт. 2017 в 20:23
Единственное, я бы добавил конденсатор на нижний резистор. Аналоговые входы у дуины без буферизации и довольно низкоомные для АЦП (большое потребление в момент замера).
Тут не понял. Параллельно нижнему резистору делителя? Какой номинал?

Добавлено 17 Окт. 2017 в 00:25

Цитата: mr.Dream от 16 Окт. 2017 в 20:37
скорость меряйте в прерываниях по периоду между импульсами - так проще и правильней. Я использовал PCINT для чтения трех датчиков холла и в прерываниях обновлял регистры, а в основной программе делал калькуляцию всего с переводом в обороты/скорость.
В это пока не вникал, придет время переспрошу, и так много новой информации)

Цитата: mr.Dream от 16 Окт. 2017 в 20:37
дисплей рекомендовал бы подключать не через параллельный интерфейс, а например через i2c. Четыре провода: два данных и два питания.
Само-собой, это я в протеусе скетч немного ковырял, i2c почему то там не захотел работать.
Строю лигерад

Dmitry__

Цитата: Yaroslav от 17 Окт. 2017 в 00:20
Очень интересный вариант, только наверное возьму INA219, их можно у нас найти а INA226 только с китая ждать.
В INA219 контакты измерения напряжения и тока совмещенные, наверное им буду только ток измерять
Любой внешний ацп будет значительно интересней чем аналоговая схема. Можно взять spi или i2c ацп для тензодатчиков или термопар, они стоят как мукА и рассчитаны на такие низкие напряжения как у шунта. Есть встроенный фильтр на фон 50/60 Гц. Из-за дешевой технологии (дельта-сигма) и низкой скорости у них разрядность от 16 до 22 бит. Правда и шум около 4 бит. До 14 бит можно смело обрезать данные. Такой ацп будет в разы лучше встроенного в avr. Для ардуин много выпускается плат ацп. Под датчик тока точно нет смысла ЛУТ-ить плату.
http://roboparts.ru/products/ad7705
http://roboparts.ru/products/gy-mcp3424

ЦитироватьТут не понял. Параллельно нижнему резистору делителя? Какой номинал?
Да, который на схеме R10. 0.1mkf за глаза :)





Добавлено 17 Окт. 2017 в 00:59

Который R9 лучше наборный из 2-х поставить, для высоковольтности...

Dmitry__

Ссылки дал на местные интернет магазины, там цены конские. Надо в поиск: "adc arduino ali"
Мои любимые дуинки на 3.3v (8 мГц) arduino pro mini 3.3v, по сто руб за пучок :) Только шить их немного сложнее, нужен usb/com переходник. Но тоже стОит 100р и покупается один раз (лучше 3, теряются иногда :))

Yaroslav

На сколько я понял в этих АЦП есть встроенный усилитель и сигнал с шунта можно усилить раз в 5 и готово?
Если они бывают 4х канальные, то одним можно измерять и ток (падение напряжения на шунте) и напряжение батарни(через делитель)?

Добавлено 17 Окт. 2017 в 01:19

Мне про мини тоже нрaвятся, в руках пока не держал, только в корзину закинул, но по параметрам интересные платки для готовых проектов. А этих кабелей на pl2303 от старых мобилок где то валяется пару штук, что нибудь придумаю.
Строю лигерад

Dmitry__

Цитата: Yaroslav от 17 Окт. 2017 в 01:15
На сколько я понял в этих АЦП есть встроенный усилитель и сигнал с шунта можно усилить раз в 5 и готово?
Да, настроил регистры и просто снимаешь данные. Как бы еще загрублять не пришлось, тензодатчики и термопары еще меньше имеют напряжение чем шунты :)
Если смотреть пдф на ацп ADS1115 (последняя ссылка на али), то он при FSR (Full-Scale Range) = ±0.256 V , имеет 16 эффективных бит до 64 DATA RATE (SPS).

Добавлено 17 Окт. 2017 в 01:32

Вообще, лучше искать ацп заточенные под ардуины, т.к. будут готовые библиотеки для работы с ними.

Yaroslav

Заказал пару модулей ads1115, будут недели через 2-3.
А пока пара вопросов.
1. Возможно считывать с двух каналов ads1115 дифференциально, а с оставшихся двух в одноканальном режиме между землей и входом?
Если не ошибаюсь ничего не мешает написать:
Цитироватьdif = ads.readADC_Differential_0_1();
adc2 = ads.readADC_SingleEnded(2);
adc3 = ads.readADC_SingleEnded(3);
и получать три измерения. Поправьте если это не так.

2. Как лучше измерять напряжение батареи с уровнем 0-1в с ads1115 или с уровнем 0-5в с входом ардуино?
Думаю что лучше 0-1в с помощью ads1115 так как большее разрешение, но нет ли подводных камней из за меньшего уровня сигнала?
Строю лигерад

edw123

#13
Цитата: Yaroslav от 16 Окт. 2017 в 19:30
сделать бортовой компьютер, который будет показывать напряжение, ток, скорость, считать мощность, потраченную энергию и т.д.
А если ещё и его в разрыв ручки газа поставить, то можно сделать токовое управление, управление по оборотам, обратную связь по температуре, нужную кривую отклика ручки...  :mus:

Yaroslav

[user]edw123[/user], да, были такие мысли) но всему свое время, сначала простые функции а потом посмотрим)
Строю лигерад

edw123

А 8бит точно не хватит для измерений? Или прямо аптекарской точности хочется? С шунта вроде в районе 0.5в идёт - вполне можно пробовать и без усилителя?

mr.Dream

[user]edw123[/user], с шунта по стандарту 75мВ. Я делал на лм358 с КУ=100 и не парился, подкрутил резистором, чтобы было на выходе чуть больше нуля, а потом первых пару ступенец оцифровки просто не учитывал. Мне нужен был именно показометр. А верней, ограничение тока. не такой уж температурный дрейф у 358 страшный, если не греть сильно :) в районе двух-трех миливольт смещение.

Касательно адс1115, может он мерить и диференциально и относительно минуса, просто перед измерениями менять конфигурацию. Я ардуиновский функции не использовал, а просто посылал ему по шине пару байт, а в ответ ловил тоже пару байт. Мне так было проще, так как перед собой сразу держал даташит с регистрами управления :) Скажу только, что при невысокой скорости квантирования и конденсаторе по входу прыгание младших бит минимальное. То есть, в режиме одноканального измерения там честных 14бит, чего хватает за глаза. И 15 бит в дифференциальном режиме. Но мне и 10 бит ардуины хватало. При 100В цена деления 0,1В - это более чем достаточно :)

edw123

Цитата: mr.Dream от 20 Окт. 2017 в 00:29
[user]edw123[/user], с шунта по стандарту 75мВ.
Это смотря с какого шунта. В велоконтроллере вроде нет никакого усилителя внешнего на сигнал с шунта и даже кажется делитель и там явно больше 75мВ.

Yaroslav

Тю, я раньше тоже думал что при 35а где то 0,6в, но оказалось ошибся на нолик :ah:.
Шунт в инфинеоне 1,7мОм, при 35а(прошито батарейного) по закону Ома 59,6мВ.
Получается что для шунта нужно использовать максимальное усиление, с диапазоном 0-0,256В.
Как измерять напряжение батареи, уложить его в диапазон 0-0,256В для ацп или 1-5в для ардуинки? Как то жалко что два канала ads1115 в воздухе висят и не используются. Может можно усиление на ходу менять, перед измерением на каждом входе изменять усиление, такое возможно??
Строю лигерад

edw123

Цитата: Yaroslav от 20 Окт. 2017 в 00:56
Тю, я раньше тоже думал что при 35а где то 0,6в, но оказалось ошибся на нолик
Шунт в инфинеоне 1,7мОм, при 35а(прошито батарейного) по закону Ома 59,6мВ.
Получается что для шунта нужно использовать максимальное усиление, с диапазоном 0-0,256В.
И что, в инфинеоне усилитель стоит? В моём контроллере с шунта на делитель и на вход цпу. А простой делитель напряжения батареи чем не подходит?

Yaroslav

[user]edw123[/user], В том то и дело что не стоит(я так думаю, да и вы подтвердили), а раз на разъем выводится сигнал без усиления, в моей конфигурации это максимум 59,6мВ. Перед измерением его нужно усилить.
Делитель подходит, вопрос в том, к каому уровню делить, к 5в для ардуино или к 0,256В для внешнего ацп(в случае, если внутреннее усиление ацп нельзя менять на ходу, перед измерением на каждом канале, пока не понял).
Строю лигерад

edw123

Цитата: Yaroslav от 20 Окт. 2017 в 01:18
[user]edw123[/user], В том то и дело что не стоит(я так думаю, да и вы подтвердили), а раз на разъем выводится сигнал без усиления, в моей конфигурации это максимум 59,6мВ. Перед измерением его нужно усилить.
Делитель подходит, вопрос в том, к каому уровню делить, к 5в для ардуино или к 0,256В для внешнего ацп(в случае, если внутреннее усиление ацп нельзя менять на ходу, перед измерением на каждом канале, пока не понял).
А зачем менять у внутреннего? Подогнать оба сигнала под один макс уровень. http://www.avdweb.nl/Article_files/Solarbike/Motor-controller/China-BLDC-motor-controller-36V-250W-circuit.jpg Батарейный сигнал можно и стабилитроном урезать для точности.

Если в контроллере нет усилителя - зачем Вам хочется?

Yaroslav

[user]edw123[/user],
ЦитироватьЕсли в контроллере нет усилителя - зачем Вам хочется?
И что, Вы предлагаете измерять 0-0,059В на входе 0-5В? Разве не стоит его усилить перед измерением? В не зависимости хочется мне или нет)

Добавлено 20 Окт. 2017 в 01:40

И так уточняю вопрос, если раньше не правильно выразился.
Такое будет работать?
Цитироватьvoid loop(void)
{
  int16_t  adc2;
  int16_t dif;
 
  ads.setGain(GAIN_SIXTEEN);
  dif = ads.readADC_Differential_0_1();

  ads.setGain(GAIN_ONE);
  adc2 = ads.readADC_SingleEnded(2);
 
}

Или ацп сгорит от того что на вход 2 будет подаваться сигнал больше чем нужно для "GAIN_SIXTEEN"?
Строю лигерад

Dmitry__

Цитата: Yaroslav от 19 Окт. 2017 в 22:02
1. Возможно считывать с двух каналов ads1115 дифференциально, а с оставшихся двух в одноканальном режиме между землей и входом?
Ничего не мешает (не увидел таких запретов в pdf). Все можно делать на ходу, и мультиплексор и PGA. Единственное, если будет режим "Continuous-conversion mode", то может понадобится останавливать, но это все легко проверить в тестовом скетче. Дать дифф. пару и одиночные сигналы на ацп и все вывести в терминалку.

А, ну [user]mr.Dream[/user] ответил на этот вопрос, все можно конфигурировать на лету.

Цитата: Yaroslav от 20 Окт. 2017 в 01:18
вопрос в том, к каому уровню делить, к 5в для ардуино или к 0,256В для внешнего ацп(в случае, если внутреннее усиление ацп нельзя менять на ходу, перед измерением на каждом канале, пока не понял).
Да все можно на ходу. Приводить напряжение к 0,256В не нужно, есть диапазон: FSR = ±6.144. Только учитывать пометку(1): This parameter expresses the full-scale range of the ADC scaling. Do not apply more than VDD + 0.3 V to this device.

Я комп делал (не доделал, ждет зимних длинных вечеров) на базе ваттметра hk_010. Вот он как раз абсолютно глючный устройств благодаря lm358 :)
Я на его разьем балансира вывел программатор, внутр. функции шунта использовать не буду хотя бы потому, что глупо вести силовые провода к рулю (внешний сенсор тока). Ваттметр сделан на atmega8, проект пишу в чистом gcc (не ардуино).



Прикол ваттметра в открытой прошивке, надоело писАть комп, залил обратно прошивку ваттметра :) Вот:





Yaroslav

ЦитироватьДа все можно на ходу. Приводить напряжение к 0,256В не нужно, есть диапазон: FSR = ±6.144.
Вот это круто,  не ожидал что усиление можно менять!) Все пугает меня тот факт что то одной ноге будет висеть вольта 4, пока на паре других измерения с диапазоном 0,256В))
Строю лигерад

Dmitry__

Ну только надо посмотреть библу ардуиновскую, может там есть косяки с переключением mux, тут я как mr.Dream, люблю полный контроль над чипами. Лучше свои функции написать. В последнее время библиотеки ардуин полны быдлокода...
Скажем так, если будет малейшее подозрение на глючность ардуиновскай функции (возитсья не дольше 3-х часов :)), то писАть свое...

edw123

Цитата: Yaroslav от 20 Окт. 2017 в 01:36
[user]edw123[/user],
ЦитироватьЕсли в контроллере нет усилителя - зачем Вам хочется?
И что, Вы предлагаете измерять 0-0,059В на входе 0-5В? Разве не стоит его усилить перед измерением? В не зависимости хочется мне или нет)
Почему-это вход "0-5В"? Внешнее опорное с нужным уровнем.

Yaroslav

Кто в курсе, какой сигнал приходит на контакт скорости разъема для цикл аналиста?
Наверное сигнал с датчика хола, короткие импульсы от 4 до 5 вольт?
Строю лигерад

batson

[user]Yaroslav[/user], да они самые, 5 вольт через резистор 10к
Самоходный аппарат из нержавейки: нержавеющий чоботар, инфинеон 12, MXUS 1000

Yaroslav

Хорошо.
Нужно выяснить сколько импульсов получу за 1 оборот.
Мк ДД, стандартный 205-й киловаттник, вроде 46 магнитов(сам не считал). Получается за один оборот 23 импульса, правильно?
Строю лигерад

Dmitry__

Забить на это. Должна быть константа как в велокомпьютере - вводишь диаметр обода на колич. импульсов...

TRO

Цитата: edw123 от 20 Окт. 2017 в 10:12
Цитата: Yaroslav от 20 Окт. 2017 в 01:36
[user]edw123[/user],
ЦитироватьЕсли в контроллере нет усилителя - зачем Вам хочется?
И что, Вы предлагаете измерять 0-0,059В на входе 0-5В? Разве не стоит его усилить перед измерением? В не зависимости хочется мне или нет)
Почему-это вход "0-5В"? Внешнее опорное с нужным уровнем.

Внешнее опорное у атмелов обычно нормируется по нижнему уровню, и обычно лишь немного ниже 1в, так что не разгонишся.

Для усиления в атмелах есть усилитель, вот только его нет в камнях на которых построены младшие модели ардуин.
Ну и ко всему, 10 бит для измерения тока как по мне маловоато (особенно с учетом что пара младших бит плывет куда хочет от "фазы луны"), поэтому я тоже за внешний АЦП.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

Yaroslav

При чем это достаточно дешево. Меньше чем за 2 бакса(на али) получаем 4 входа с бОльшим разрешением чем в ардуино, плюс в ацп есть собственный опорник на борту.
Строю лигерад

mr.Dream

В аруинки (меги328) тоже есть внутренний опорник, 2,56 и 1,1В (+-10% изначально, но достаточно термостабильны, но есго значение можно предопределить методом научного тыка)
Попробуйте делать "для чайника", начиная с простого, а добавить внешний АЦП успеете :)

Добавлено 21 Окт. 2017 в 14:26

извиняюсь, в 328 только 1,1В (обычно 1,055-1,090)

Dmitry__

Большое разрешение нужно для подсчета потраченной энергии, или для подобных функций. Т.к. там идет интегрирование, то никакого внутр. ацп не хватит для этого. Внутр. ацп и lm358 - только для показометров. Я приводил в пример ваттметр hk-010, он со своим lm358 врет безбожно. Есть еще одна кЕтайская поделка на авр для измерения тока, светил ее в теме переделки двигателя от стиралки LG, тоже врет безбожно, токи ниже 2-х ампер просто не показывает.

mr.Dream

Ну ладно, разрешение 0,1% разве мало? Даже если откинуть пару младших бит, да пусть 0,4%. Зачем больше точности для измерения емкости? :) Тут больше ошибка измерений будет от малой частоты пересчета, и ее нужно делать относительно большой, а не раз в секунду. Так как за секунду, ток может подняться до пика и упусть до нуля. Частично спасет RC-интегратор, но это будет влиять на показания реального времени, если его постоянная времени будет сильно больше от частоты обновления дисплея :)
Допустим, на батарее я проезжаю 50км ровно.  Сильно ли изменит ситуацию, если я не доеду 200 метров из за 0,4% ошибки измерения ?  да там остаточная емкость будет в разы больше зависить от снимаемого тока и температуры, чем от такой вот погрешности :)
Нужно сначала определиться, нужна ли сверх высокая точность, или высокой достаточно? :)

Dmitry__

Цитата: mr.Dream от 21 Окт. 2017 в 15:09
Тут больше ошибка измерений будет от малой частоты пересчета, и ее нужно делать относительно большой, а не раз в секунду.
Дельта-сигма тем и хороша что она сама интегрирует данные, нет наложения спектров (алиасинг) , но конечно надо вкл. внутр. фильтр и включать непрерывный режим
Цитата: mr.Dream от 21 Окт. 2017 в 15:09
Допустим, на батарее я проезжаю 50км ровно.  Сильно ли изменит ситуацию, если я не доеду 200 метров из за 0,4% ошибки измерения ?
Если остановиться на часок, а потом поехать, то ошибка будет не 0.4%, a 400% :) Интегрирование ошибки...

mr.Dream

Цитата: Dmitry__ от 21 Окт. 2017 в 15:48
Если остановиться на часок, а потом поехать, то ошибка будет не 0.4%, a 400% :) Интегрирование ошибки...
что то вы сильно утрируете :) Если остановиться, то никакой ошибки и не будет. Если речь идет за разрядность ацп, то эта ошибка разве только на малых токах будет влиять (фонарь, скажем).  Но если нужно имеь прибор, способный мерить милиамперы слаботочного потребления на фоне 100А "рабочих", то да, ads11xx тут более приемлемо, проще и дешевле хорошого инструментального ОУ.  Для каждой цели - свое решение. Я исхожу из названия темы. Если бы была цель создать сразу полноценный суперпроцессиональный борткомпьютер - то и рекомендации были бы другими. Но человек хочет поучиться, попробовать. А хорошие идеи придут в процессе.
ВОт у меня была задача - мерить пиковый ток мотора, зная батарейный ток и скважность ШИМ, и по нему делать ограничение. А еще была задача грубо считать ампер*часы батареи, чтобы приблизительно знать остаток энергии в батарее.  Ардуина и лм358 был под рукой, с этого и деллал. от 1А до 50А показания совпадали с ваттметром тюрниджи, на меньшем токе был небольшой "подьем" показаний ближе к нулю, и вместо нуля было пару процентов, так как искуственно задрал смещение нуля, чтобы вывести в линейны режим, а в программе просто эту разницу компенсировал, кроме того - не считал ток меньше 200мА, так как не нужно было.

Dmitry__

Цитата: mr.Dream от 21 Окт. 2017 в 16:10
что то вы сильно утрируете :) Если остановиться, то никакой ошибки и не будет.
Не утрирую, учесть все моменты с накоплением интеграла очень сложно. Но всякая нелинейность делает из ваттметра кусок ненужной кЕтайской какашки, коих у меня предостаточно :)
Когда делал гироскоп с минимальным дрейфом на крутом мемс от аналогдевиц (ADIS16250), то у меня в программе были 64 битные аккумуляторы для перевода угловой скорости в абсолютные углы, и то все уплывало через 5 минут.
Может и получается и слишком "с запасом", но если начинать от встроенных возможностей микроконтроллера, а потом понять что нужен учет энергии, то весь проект можно будет выкинуть и начинать с нуля. Тем более внешние ацп как раз проще для новичка, правильно собирать аналоговую схему с ацп и схемами нормирования сигнала надо еще уметь, а тут просто кубики. ..

Yaroslav

#39
Слепил кусок кода, пока без ads1115.
В протеусе работает. Что скажете? Может нужно что изменить, или улучшить?
кусок кода
// Время обновления показаний
#define PERIOD  200

// Аналоговые входы
#define PIN_VOLT A0
#define PIN_AMP A1


const float VRef = 5.0149;                            // Опорное напряжение 5в
const float Divider = (100.0 + 5.1) / 5.1;            // Коэффициент делителя (R1 + R2) / R2.
const float Shunt = 1.7;                              // Сопротивление шунта.
float InVolt, Volt, InAmp, Amp, Div, Watt, WtP, WtH;

void setup() {
  // Инициализация дисплея
  lcd.begin (16, 2);
  lcd.clear();
  lcd.print("V=");
  lcd.setCursor (9, 0);
  lcd.print("A=");
  lcd.setCursor (0, 1);
  lcd.print("W=");
  lcd.setCursor (9, 1);
  lcd.print("WH=");
}

void loop() {
  // Чтение из порта с усреднением
  unsigned long ReadTime = millis();
  int Count = 0;
  InVolt = 0;
  InAmp = 0;
  while ((millis() - ReadTime) < PERIOD) {
    analogReference(DEFAULT);
    InVolt += analogRead(PIN_VOLT);
    analogReference(INTERNAL);
    InAmp += analogRead(PIN_AMP);
    Count++;
  }
   InVolt = InVolt / Count;
   InAmp = InAmp / Count;

  // Обработка данных
  Volt = InVolt * Divider * VRef / 1023;
  Amp = (InAmp * 1.1 / 1023 / Shunt) * 1000;
  Watt = Volt * Amp;
  WtP += Watt;
  WtH = WtP /(1000 / PERIOD) / 3600;
 
  // Вывод данных
  lcd.setCursor (2, 0);
  lcd.print(Volt, 2);
  lcd.setCursor (11, 0);
  lcd.print(Amp, 2);
  lcd.setCursor (2, 1);
  lcd.print(Watt, 0);
  lcd.setCursor (12, 1);
  lcd.print(WtH,0);
}
Строю лигерад

Dmitry__

Лучше в будущем уходить от плавающей точки. Во-первых сразу прибавится или 2 или 4 кб. (не помню точно), а во-вторых обработка плав. точки для 8-ми битной аврки - ад и Израиль :)
А так: код как код, протеусу полностью верить не стоит, лучше все в железе проверять...


edw123

Цитата: Dmitry__ от 21 Окт. 2017 в 16:37...
Когда делал гироскоп с минимальным дрейфом на крутом мемс от аналогдевиц (ADIS16250), то у меня в программе были 64 битные аккумуляторы для перевода угловой скорости в абсолютные углы, и то все уплывало через 5 минут...
Круто, круто, особенно "для чайников". :-D Повышая точность там, где нет для этого никаких жизненно важных оснований (хотя бы исходя из природы измеряемого процесса) мы создаём лишние бесполезные сущности, не говоря о затратах денег, времени и возможной головной боли по лишнему анализу причин отклонений суперточной величины от очевидной. :exactly:
Не, батарейка часто кончается "за 100м до дома" :), но и бензин в 50л баке аналогично. Не в точности измерометра проблема.

Dmitry__

Ну если у тебя самокат имеет аккум 20ач, стоИт 10 часов и потребляет 1 ампер, а прибор видит 0 ампер. За 10 часов сьедается пол аккума 10ач, ферштейн? :)

edw123

Цитата: Dmitry__ от 21 Окт. 2017 в 22:23
Ну если у тебя самокат имеет аккум 20ач, стоИт 10 часов и потребляет 1 ампер, а прибор видит 0 ампер. За 10 часов сьедается пол аккума 10ач, ферштейн? :)
Йа, йа, но не настолько всё плохо в жизни. И куча более прагматичных ситуаций , когда всё будет в ажуре.

Dmitry__

Куда еще прагматичней? Это при ошибке 1% от полной шкалы 100 ампер - полный разряд аккума за сутки. А по прибору еще можно ехать 40 км :)
Нафиг нужен такой компьютер?

edw123

Цитата: Dmitry__ от 21 Окт. 2017 в 22:46
Куда еще прагматичней? Это при ошибке 1% от полной шкалы 100 ампер - полный разряд аккума за сутки. А по прибору еще можно ехать 40 км :)
Нафиг нужен такой компьютер?
При ошибке в 0.1% если самокат простоит 1000часов, то батарея окажется разряженной полностью. Неожиданно. :eek:
Да я и не уговариваю, просто размышляю над разумной степенью чайниковости...

mr.Dream

Был у нас когда в городе то небольшой фотоклуб, сайт с фотогалереей, форум, организовывали встречи. Подавляющее большинство - начинающие фотографы и просто любители. Потом туда "пришли" свадебные бомбилы, и начали всем тереть, что мол композиция не та, свет не тот, цвет не тот, шумы, ГРИП, динамический диаазон, поза, контрастность, насыщенность, ракурс, детали, да все не то. Вот смотрите, мол, как надо! Показывали идеальные на их взгляд и фотоканонам снимки. Но все они были шаблонные, ничем не отличались от остальной серой массы. В результате большиснтво участников покинули клуб, так как начали считать себя неполноценными. Сайт загнил. Форум молчит. Про живые встречи и речи не идет.  А если бы все было по другому, никто не указывал "как надо", а если чуть не так - то уже брак? Возможно, и до сих пор клуб был бы жив. Как по мне, там много интересных личностей было, для которых фото - не профессия, и они не пытались сделать идеальный кадр, а для них это хобби, возможность себя реализовать творчески.
Аналогично и здесь. Если бы это было инженерное бюро и ставилась цель сделать прецезионный ваттметр... но топик создан для абсолютно другого. Ярослав, бери и делай - только сразу в железе. Практика - лучший учитель. Понимание того, что именно нужно, придет со временем.  А насчитает он 20 или 20,5 А*ч - это мелочи. Направление ветра на порядки больше "искажает" показания, нежели дрейф ОУ и дискретность АЦП :)

Dmitry__

Цитата: mr.Dream от 21 Окт. 2017 в 23:49
Был у нас когда в городе
Тем не менее, ТС больше понравился мой совет, а не грабли lm358... :)  :kidding:

Yaroslav

Что то математик с меня хреновый, время между импульсами вроде получил, но никак не могу перевести его в об/мин, туплю постоянно.
Кто знает как это сделать?
void setup() {
  attachInterrupt(0, impuls, RISING);    //внешние прерывания по фронту импульса на входе D2 и вызов функции "impuls"
}

void impuls(){
  tImpuls = micros() - tImpuls2;
  tImpuls2 = micros();
}

void loop() {
Speed = tImpuls ????;
}
Строю лигерад

mr.Dream

[user]Yaroslav[/user], частота = 1 / период :)
ну а далее переводить из секунд в часы, подставлять длину окружности. Но чтобы не было очень "странных" результатов, единицу заменить некоторой константой, чтобы не оперировать очень маленькими числами.

TRO

#50
[user]Yaroslav[/user], Взять минуту в тех же еденицах и поделить на время между импульсами.

Я когда делал свой ваттметр, ушел от секунд, и привязался к часам (ибо еденицы отсчета ваттчасы, амперчасы, километры в час). В итоге опрос и приращение накопительных счетчиков (избыточной разрядности) происходит 10 000 раз в час (через каждые 0,36 секунды). На экран все выводится путем перемещения запятой и отбрасыванием лишних десятичных знаков.

Один из вариантов ваттметра я пытался делать на вайфай модуле ESP826 (привет ардуинщикам, этот вай фай модуль для которого есть ардуиновская прошивка, т.е. ардуина эмулируется у него внутри). Я же писал на луа... в общем прототип работает, все показывает на обновляемой веб странице, и считает как полноценный ваттметр, но из за врожденных кривостей модуля, стабильно переодически вешается (в итоге поставив байк на зарядку с этим ваттметром, можно не увидеть конечного результата, повесившись перестает выдавать страницу и не дает переподключится, хотя судя по ногодрыгам - цикл программы ватметра работает). В итоге разработку на этом модуле я забросил.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

FobOrgan

[user]Yaroslav[/user], когда будете считать пробег, то в ардуине нет типов данных больше 4 байт, так что если завести переменную пробега в миллиметрах и прибавляя к ней периметр колёса в мм общий пробег на типе unsigned long пойдёт на второй круг после примерно 4500км, что для электровела мало.
Так же и с float нужно аккуратно, если начнёте считать приращение разных тат Втч и Ач за какие то сотые-десятые секунды, то  могут получаться очень микроскопические значения, которые будут просто считаться нулём. Их нужно будет считать и суммировать отдельно пока не "вырастут" до удобоваримых и потом прибавлять к общему счётчику. Mr Dream именно это имел ввиду.
Езжу на 2хQ100/1200Вт/14Sx18Ач Li-ion уже 33300км за 9 лет

Yaroslav

С делением на очень маленькие значения уже сталкивался, понял что они за ноль считаются)
Строю лигерад

Yaroslav

Со скоростью вроде разобрался, вышло так:

  Speed = ((1000000 / tImpuls) / 23) * 1.73 * 60 / 1000;

Только что то мне не очень нравится эти микросекунды периода засекать потом этот пересчет. В МК не заливал но протеус знатно тормозит при 400 оборотах, это ж 9200 импульсов. Может тормоза из за эмуляции, может в ардуинке не будет тормозить? В общем завтра проверю на железе.
Строю лигерад

Yaroslav

Хочу немного усреднить длину импульса, не получается. Хотел добавить в while и делить на Count но выдает билиберду.
Как правильно усреднить tImpuls что бы выводилось 5 раз в секунду как и остальные показания?
// Время обновления показаний
#define PERIOD  200

// Аналоговые входы
#define PIN_VOLT A0
#define PIN_AMP A1


const float VRef = 5.0149;                            // Опорное напряжение 5в
const float Divider = (100.0 + 5.1) / 5.1;            // Коэффициент делителя (R1 + R2) / R2.
const float Shunt = 1.7;                              // Сопротивление шунта.
float InVolt, Volt, InAmp, Amp, Div, Watt, WtP, WtH, Speed;
unsigned long tImpuls = 0;

void setup() {
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING); //Внешние прерывания по фронту импульса на входе D2 и вызов функции "impuls"
 
  // Инициализация дисплея
  lcd.begin (16, 2);
  lcd.clear();
  lcd.print("V=");
  lcd.setCursor (9, 0);
  lcd.print("A=");
  lcd.setCursor (0, 1);
  lcd.print("W=");
  lcd.setCursor (9, 1);
  lcd.print("WH=");
}

void impuls(){
  unsigned long tImpuls2 = 0;
  tImpuls = micros() - tImpuls2;
  tImpuls2 = micros();
}

void loop() {
  // Чтение из портов с усреднением
  unsigned long ReadTime = millis();
  int Count = 0;
  InVolt = 0;
  InAmp = 0;
  while ((millis() - ReadTime) < PERIOD) {
    analogReference(DEFAULT);
    InVolt += analogRead(PIN_VOLT);
    analogReference(INTERNAL);
    InAmp += analogRead(PIN_AMP);
    Count++;
  }
   InVolt = InVolt / Count;
   InAmp = InAmp / Count;
   
  // Обработка данных
  Speed = ((1000000 / tImpuls) / 23) * 1.73 * 60 / 1000;
  Volt = InVolt * Divider * VRef / 1023;
  Amp = (InAmp * 1.1 / 1023 / Shunt) * 1000;
  Watt = Volt * Amp;
  WtP += Watt;
  WtH = WtP /(1000 / PERIOD) / 3600;
 
  // Вывод данных
  lcd.setCursor (2, 0);
  lcd.print(Volt, 2);
  lcd.setCursor (11, 0);
  lcd.print(Amp, 2);
  lcd.setCursor (2, 1);
  lcd.print(Watt, 0);
  lcd.setCursor (12, 1);
  lcd.print(WtH);

  Serial.println(Speed);
}
Строю лигерад

TRO

#55
[user]Yaroslav[/user], Делайте асинхронно, не надо пересчитывать с каждым приходом импульса, чтобы проц не перегружать. Просто записывайте время между импульсами в отдельную себе переменную, обновляя ее с приходом каждого импульса по прерыванию от него. А потом в общем прерывнии (когда все пересчитываете, я так понял 5 раз в секунду) читайте из переменной и делайте пересчет, я не думаю что за секунду или её пятую часть скорость значительно изменится.

Лучше время не усреднять, а увеличить точность подсчета времени между импульсами (частоту на счетный таймер поднять). Но если хочется усреднять, то плавающее среднее в помощь. Берете 10 переменных, и пишите в них считываемое значение по очереди, результат каждый раз складываете и делите на 10 (я не делю, я запятую при выводе на экран передвгаю). Можно еще фильт кальмана посмотреть, что бы на количестве переменных съэкономить.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

Yaroslav

Залил прошивку в ардуино. Выяснилось пару проблем.
1. Перед измерением напряжение с шунта опорное не переключается на INTERNAL 1,1в меряет относительно 5в. Я что то не так делаю, или это и не должно работать?(в протеусе работало)
2. Так как отдельного генератора не имею, нагуглил простенький код генератора импульсов, шимлю 9 выходом на 2 вход, скорость показывает, но циклично проскакивают заниженные на пару км измерения. Не пойму из за чего это может быть?
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f,16,2);


// Время обновления показаний
#define PERIOD  200

// Аналоговые входы
#define PIN_VOLT A0
#define PIN_AMP A2


const float VRef = 4.94;                             // Опорное напряжение 5в
const float IntRef = 1.10;                            //Калибровка внутреннего опорного напряжения 1.10в.
const float Divider = (100.0 + 5.1) / 5.1;            // Коэффициент делителя (R1 + R2) / R2.
const float Shunt = 1.7;                              // Сопротивление шунта.
const byte Polus = 23;                                // Количество пар полюсов МК
const float DR = 1.73;                                // Длина колеса 2*P*R м.
float InVolt, Volt, InAmp, Amp, Div, Watt, WtP, WtH, Speed;
unsigned long tImpuls = 0;
unsigned long tImpuls2 = 0;


void setup() {                 
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING); //внешние прерывания по фронту импульса на входе D2 и вызов функции "impuls"
 
  // Инициализация дисплея
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.print("V=");
  lcd.setCursor (9, 0);
  lcd.print("A=");
  lcd.setCursor (0, 1);
  lcd.print("W=");
  lcd.setCursor (9, 1);
  lcd.print("WH=");

  //генератор
  pinMode(9,OUTPUT);
  TCCR1A=(1<<COM1A1)|(1<<WGM11);
  TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
  OCR1A=0; ICR1=0;
}

void impuls(){
  tImpuls = micros() - tImpuls2;
  tImpuls2 = micros();
}

void loop() {
  //генератор
  ICR1= (F_CPU/13800)-1;
  OCR1A=  ((float) 0.625 / 0.0625 ) -1  ;
   
  // Чтение из порта с усреднением
  unsigned long ReadTime = millis();
  unsigned long ImpulsRead = 0;
  int Count = 0;
  InVolt = 0;
  InAmp = 0;
  while ((millis() - ReadTime) < PERIOD) {
    analogReference(DEFAULT);
    InVolt += analogRead(PIN_VOLT);
    analogReference(INTERNAL);
    InAmp += analogRead(PIN_AMP);
    Count++;
  }
   InVolt = InVolt / Count;
   InAmp = InAmp / Count;

   if (ReadTime >= PERIOD){
    ImpulsRead = tImpuls;
}
  // Обработка данных
  if (tImpuls > 0){
    Speed = ((1000000 / ImpulsRead) / Polus) * DR * 60 / 1000;
}
  else{
    Speed = 0;
  }
 
  Volt = InVolt * Divider * VRef / 1023;
  Amp = ((InAmp * 1000) * IntRef) / 1023 / Shunt;
  Watt = Volt * Amp;
  WtP += Watt;
  WtH = WtP /(1000 / PERIOD) / 3600;
 
  // Вывод данных
  lcd.setCursor (2, 0);
  lcd.print(Volt, 2);
  lcd.setCursor (11, 0);
  lcd.print(Amp);
  lcd.setCursor (2, 1);
  lcd.print(Watt, 0);
  lcd.setCursor (12, 1);
  lcd.print(WtH);

  //lcd.setCursor (2, 0);
  //lcd.print(Speed, 2);
 

  Serial.println(Speed);
}
Строю лигерад

TRO

Я на всякий случай перед каждым измерением конфигурирую опорное и выбираю вход, после чего делаю одно холостое измерение АЦП которое не учитываю, после него небольшая пауза на устаканивание компараторов АЦП, опоры и аналоговых входов, потом уже делаю десять опросов АЦП с небольшими паузами между ними и суммированием результата в одной переменной. Потом как я уже писал, результат пишу в одну из десяти переменных, меняя их по очереди в каждом цикле, их суммирую в каждом цикле (получаю плавающее среднее, которое растягивает резкие изменения сглаживая до 3.6 секунды, визуально цифры поприятнее на экране скачут, и псевдо улучшают динамическое разрешение).

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

Yaroslav

[user]TRO[/user], можете показать кусок кода для примера?
Строю лигерад

FobOrgan

На моём опорное внешнее, ну как внешнее, на самой ардуине есть стабилизатор на 3.3В. Есть ардуино нано c microUSB разъёмом, на ней стоит стабилизатор LM1117он очень стабилен по температуре. Замораживал - подогревал, уход напряжения гораздо меньше 1%. На других arduino nano, которые с miniUSB стоит другой стабилизатор - заметно похуже.
Используя генератор для имитации датчика скорости вы себя лишаете прелестей дребезга контактов, например герконов, не у всех же ДД двигатели, редукторники тоже не редкость и нужен внешний датчик с 1 магнитом на оборот, что кстати тоже даёт неудобства, т.к. на скорости 5км/ч от этого датчика приходит 1 сигнал в 1.5сек. Если осреднять по 10 значениям в лоб, то в таких условиях при резком замедлении можно ещё достаточно долго будет любоваться огромной скоростью спидометра. Мой алгоритм туп, он если видит резкое снижение скорости, то обнуляет значения где скорость была высокой и начинает считать только по вновь появляющимся данным. При остановке соответственно ждёт секунды 2.5-3 и потом весь массив зануляет - остановка.
Для осреднения значений лучше сразу сделать класс в котором можно выбирать сколько значений будет участвовать, т.к. прыгают они по разному, а излишнее осреднение тормозит реальность происходящего.
Езжу на 2хQ100/1200Вт/14Sx18Ач Li-ion уже 33300км за 9 лет

Yaroslav

#60
[user]FobOrgan[/user], приедет ads1115 проблем с опорным напряжением вообще не будет, там у него есть свой опорник. Это я временно на входах ардуино тренируюсь.
По поводу геркона, у меня дд, плюс у финика есть выход под СА, раз есть такие ресурсы, работаю с ними. Ардуино в первый раз увидел недели 2 назад, так что все что делаю приходится изучать на ходу, раньше с таким никогда не сталкивался. И задача не стоит создать универсальный прибор который подойдет всем, делаю под себя, а если кто захочет повторить, сможет допилить как ему захочется)
Строю лигерад

TRO

#61
Цитата: Yaroslav от 23 Окт. 2017 в 18:12
[user]TRO[/user], можете показать кусок кода для примера?
Я на бейсике пишу, скетчи выпекать не умею.
Вот на вскидку пример подпрограммы опроса АЦП.
Цитировать _adc1:
'-------------------------------------------------------------------------------
    Waitms 16
Start Adc
    W = Getadc(0 , A)
    Waitms 1
    W = Getadc(0 , A)
   For I = 1 To K
   Waitus 250
   W = W + Getadc(0 , A)
   Next
Stop Adc
'-------------------------------------------------------------------------------
  Return
Конфигурацию АЦП и опоры задаю перед вызовом этой подпрограммы.
Так же перед вызовом подпрограммы выбирается доп. конфиг (типа внутреннего усиления, переменная "А") и сколько раз (задается переменной "К") опросить АЦП и просуммировать.
Видно что первый опрос холостой, потом пауза в 1 миллисекунду, потом первый опрос, и цикл дополнительных опросов с паузами и суммированием.
А плавающее среднее из десяти переменных делаю уже в основной программе.
Мой код вам в лоб все равно не подойдет, ибо язык другой, тут главное алгоритм перенять, и взять то что вам подойдет.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

Yaroslav

В бейсике ни грамма не понимаю) но вижу что там можно прочсто "wait", в аруино если написать "delay" то проц останавливается и в это время ничего не делает, ждет :facepalm:, приходится засекать и отнимать милисекунды   :ireful:
А усреднение что в скетче очень даже не плохо работает, кручу на железе, цифры не прыгают, изменять не буду.
Строю лигерад

edw123

Цитата: Yaroslav от 25 Окт. 2017 в 23:34
В бейсике ни грамма не понимаю) но вижу что там можно прочсто "wait", в аруино если написать "delay" то проц останавливается и в это время ничего не делает, ждет :facepalm:, приходится засекать и отнимать милисекунды   :ireful:
А усреднение что в скетче очень даже не плохо работает, кручу на железе, цифры не прыгают, изменять не буду.
Если [user]TRO[/user] пишет тоже для Ардуино, то от языка не должно зависеть, кмк. Разве что какой-нибудь очень крутой компилятор, который wait переделывает через прерывание.

TRO

Цитата: Yaroslav от 25 Окт. 2017 в 23:34
В бейсике ни грамма не понимаю) но вижу что там можно прочсто "wait", в аруино если написать "delay" то проц останавливается и в это время ничего не делает, ждет :facepalm:, приходится засекать и отнимать милисекунды   :ireful:....
А не надо основной цикл гонять по кругу, настройте таймер и вызывайте этот цикл по прерыванию, и вам будет фиолетово на время выполнения кода, главное что бы все успевало посчитатся за время этого цикла. И вообще все времяизмерительное должно быть по прерываниям, в идеале от внешних часов реального времени.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

i

Для привязки действий ко времени я использую "машину времени" - это набор программных таймеров, работающих от одного аппаратного.
Вот например как у меня написан цикл мигания светодиодом:
code Migni \ пример переодичной работы
    begin
        ldiW X,1 sek 2/ rcall Delay:
        if_b Red \_ Red else _/ Red then
    again
    c;

в ассемблере это выглядит так:
Migni:      LDI   R27,0
            LDI   R26,8
            RCALL Delay:
            SBIS  PORTA,4
            RJMP  m93
            CBI   PORTA,4
            RJMP  m94
m93:        SBI   PORTA,4
m94:        RJMP  Migni


Хотя это бесконечный цикл, отдельная подзадача, он не мешает выполнению основной программы.
Фокус в подпрограмме Delay: Она получает не только  время задержки (через регистр Х), но и адрес возврата (через стек). Эти данные она сохраняет в памяти и возвращает управление, но не туда откуда её вызвали, а основному циклу.
Основной цикл проверяет аппаратный таймер и когда тот сработает, вызывает подпрограмму которая пробегается по программным таймерам и уменьшает на единицу их счетчики. Если у кого-то счетчик стал нулевым, то делается переход по адресу сохраненному в этом таймере.
В рассматриваемом примере, код после rcall Delay: будет выполнятся каждую полусекунду. При этом на полсекунды повиснет только эта подзадача, а остальные продолжат выполнение.
Не знаю, как это можно сделать на бейсике или скетчах, но в Си подобное реализуется через callback.

TRO

Цитата: i от 28 Окт. 2017 в 13:16
в ассемблере это выглядит так:
....
Не знаю, как это можно сделать на бейсике или скетчах, но в Си подобное реализуется через callback.
Настоящий програмист может писать код в любом языке программирования.... на ассемблере. (старый жизненный прикол)

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

edw123

Цитата: i от 28 Окт. 2017 в 13:16
Для привязки действий ко времени я использую "машину времени" - это набор программных таймеров, работающих от одного аппаратного.
...
Основной цикл проверяет аппаратный таймер и когда тот сработает, вызывает подпрограмму которая пробегается по программным таймерам и уменьшает на единицу их счетчики.
А если в основном коде ожидание события/ввода или длинный вывод происходит?

TRO

[user]edw123[/user], события ввода должны крутится по своим прерываниям, а подпрограмма их опроса должна складывать данные по полочкам и выставлять флаги, что мол событие лучилось и на полках есть данные нуждается в обработке. А длинный вывод, можно всегда разбить на много коротких. В общем есть богатая культура программирования по правильному написанию кода, куча литературы. Очень полезно пользоваться чужими  изящными и оптимальными решениями, чем городить кучу не оптимального кода.

Еще Петя Нортон писал, что если хотите научится программировать, читайте чужие программы.

Wahoo 2012 29er, +собран складной двухосис на раме"Land Rover" 69er с эл. мотором, и и МОНОКОЛЕСО

i

У меня в программе есть два очень критичных прерывания, от скорости реагирования на них зависит работоспособность всей программы. Поэтому я стараюсь избегать навешивания иных прерываний. В крайнем случае разрешаю прерывать некритичное прерывание.
Любое событие сначала поднимает аппаратный флаг, а потом уже срабатывает прерывание, если это разрешено. Все флаги можно гасить как аппаратно (при переходе на вектор прерывания), так и программно (обычно записав в него 1).
При длинном выводе я в основном цикле читаю флаг передатчика, если флаг поднялся - кидаю очередной байт в аппаратный буфер, гашу флаг и ухожу по другим делам, аппарат уже далее сам пыхтит, выдавливая байт наружу.
Так же и по событиям, как только поднимается флаг - обрабатываю.
В общем основной цикл только тем и занимается, что проверяет разные флаги и реагирует на них.

edw123

Цитата: TRO от 28 Окт. 2017 в 16:55... В общем есть богатая культура программирования по правильному написанию кода, куча литературы. ...
Конечно есть, но и люди есть, для которых это не профессия, а так, пока чай остывает... Я с сотню скетчиков разных понаписал, но до сложностей некогда и поэтому первое, что мне бы точно наделало проблем - вывод данных в терминал. Конечно - это не высшее образование в программировании м-к, но я и не претендую, а программки работают, меряют, моргают... И как раз по теме"чайниковости". :pardon:

mr.Dream

Начали за здравие, кончили за упокой))))
Нету в "техзадании" сильно привязаных ко времени выполнения задач.

В произвльном порядке в цикле основной программы, можно даже раз в несколько проходов, дахо ть раз в секунду, делаем измерения, умножаем на время, прошедшее с предыдущего измерения, складываем в какую то переменную, при ее переполнении увеличиваем на единицу еще одну переменную, а при ее - еще следующую, а "остатки от деления"  оставляем. Таким образом, будем иметь возможность считать 32-48битные значения. Считаем точно, а выводим на экран с "округлением", то есть читаем только переменные с более "крупными" записями. Это чтобы ватт*часы считать.

а с километражом там еще проще, считать "тики" в прерываниях, хоть с ДХ мотора, хоть с геркона колеса и умножать на "длину окружности колеса для одного тика". Параллельно считаем период между тиками для вывода текущей скорости.