avatar_UriBas

Моргалка на Arduino. Этюды для начинающих.

Автор UriBas, 08 Март 2017 в 16:08

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

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

Alex_Soroka

Цитата: Serg от 12 Фев. 2018 в 15:31
Да это все равно сколько тактов и какая частота.
раз.
ЦитироватьВы не понимаете принципа работы АЦП.
два
ЦитироватьНачинается преобразование с "защелкивания"  аналогового значения.
три
:facepalm:
Это как раз вы не понимаете как работает АЦП. Но упорно лезете в спор ради спора.

Serg

Вы флудите.
1. Мне действительно все равно сколько вы используете тактов и какая у вас частота.
2. Ваше заявление не доказано.
3. Без фиксации аналогового значения на конденсаторе преобразование не начинается - это аксиома. Всего 1.5 такта отведено на устаканивание мультиплексора и входных цепей.  Затем происходит "защелкивание" аналогового значения. Затем методом последовательных приближений происходит преобразование в цифру в течении оставшихся тактов.


Дм.

Глядя на последние страницы, только соглашусь:
Цитата: Яков93 от 12 Фев. 2018 в 15:30хотя слишком углубленно копаете для "начинающих"
что выяснения, кто на свете всех милее лучше "понимает работу АЦП" - не к месту в теме, предназначенной для непосвященных.

Serg

#849
Цитата: Дм. от 15 Фев. 2018 в 11:52в теме, предназначенной для непосвященных.
Так непосвященых берут на слабо. И они ведутся, как корюшка на поролон.
А.Сорока пишет, что он делает задержку в сколько-то там времени (или тактов), после переключения мультиплексора входов АТмеги для упокоения переходных процессов.
Оказалось при внимательном прочтении ПДФ-ки(дьявол в деталях), что переключение происходит только после начала процесса преобразования по фронту первого такта, и не связанно с записью нужного числа(с номером входа) в соответствующий регистр.  Можете переписывать это значение сколько угодно в произвольный момент времени. Но физическое переключение не произойдет, если не вы зададите команду на преобразование или не придет черед следующему последовательному преобразованию(см. выше тайминг, и прямым текстом в ПДФ).
Это говорит о том, что человек не понимает, что  для чего делает. ...

Все его ЗУ работает не благодаря, а просто вопреки разработчику.

ПС Еще берет на себя смелость давать глубокобессмысленные советы по программированию. Уж лучше бы ничего не писал, только вредит самому себе.

mr.Dream

А зачем такие сложности? Это всего лишь контроллер заряда) хотите лишние такты на успокоение - делайте. Не хотите - следуйте тому, что заложили разработчики и что пишет в даташите) Быстродействия хватит на всех даже через медленный analogRead))
Это ведь тема для начинающих, и усложнять её принципом работы АЦП последовательного приближения не имеет смысла для новичка. Хотя поверхностное понимание никогда не помешает.
Начинающий программист использует чужие библиотеки.
Продвинутый пишет все вручную.
А профессионал создаёт свои функции и классы, которыми пользуется только он, ээкономя своё время )

Serg

Цитата: mr.Dream от 15 Фев. 2018 в 14:08хотите лишние такты на успокоение - делайте.
Тут нет нашей или вашей хотелки. Нельзя ввести задержку тактами. От начала физического переключения мультиплексора( и кроме того выбора опорного источника)  - полтора такта до начала последовательного приближения. Получите и распишитесь за то, что было на входе ровно 13 тактов назад. Заложено в логику работы АЦП.
ПС Хотите выше 200 кГц тактовую частоту - пожалуйста, и вот только тогда: здравствуйте переключения мультиплексора и время заряда емкости хранящей аналоговое значение. Соответственно, с потерей точности в младших разрядах. О чем прямо и однозначно сказано в методичке

UriBas

Цитата: Serg от 15 Фев. 2018 в 12:45А.Сорока пишет, что он делает задержку в сколько-то там времени (или тактов), после переключения мультиплексора входов АТмеги для упокоения переходных процессов.
Оказалось при внимательном прочтении ПДФ-ки (дьявол в деталях), что переключение происходит только после начала процесса преобразования по фронту первого такта, и не связанно с записью нужного числа(с номером входа) в соответствующий регистр.  Можете переписывать это значение сколько угодно в произвольный момент времени. Но физическое переключение не произойдет, если не вы зададите команду на преобразование или не придет черед следующему последовательному преобразованию (см. выше тайминг, и прямым текстом в ПДФ). 
Господа профи! Хорошо бы примерчик с кодом..  как правильно и не правильно, с выводами и цифрами.  К примеру, интересно было бы знать разницу во времени, какой выигрыш и т.д.   ( .. дьявол в деталях, а Бог еще глубже).   
Восточная мудрость - "Шакал воет - караван идет"  Эл.вел. 350Вт.   Верую в Иисуса Христа, НЛО.  тема "продвинутой моргалки" https://electrotransport.ru/index.php?msg=1669651

Cyberpapa

Цитата: UriBas от 15 Фев. 2018 в 14:34Хорошо бы примерчик с кодом..  как правильно и не правильно, с выводами и цифрами.
Цитата: Alex_Soroka от 07 Нояб. 2016 в 19:13а ключи от квартиры вам не отдать? и от сейфа ?

UriBas

Цитата: Cyberpapa от 15 Фев. 2018 в 18:21
Цитата: UriBas писал Сегодня в 14:34 
ЦитироватьХорошо бы примерчик с кодом..  как правильно и не правильно, с выводами и цифрами.
Цитата: Alex_Soroka писал 07 Ноя 2016 в 19:13
Цитироватьа ключи от квартиры вам не отдать? и от сейфа ?
Тут не просят авторский алгоритм заряда открыть, а элементарно, поделится опытом и показать на примере преимущество того или иного метода - привязав к коду Ардуино.  Тут тема для начинающих Ардуинщиков, а не для пишущих диссертацию о методах измерений на ассемблере.
Восточная мудрость - "Шакал воет - караван идет"  Эл.вел. 350Вт.   Верую в Иисуса Христа, НЛО.  тема "продвинутой моргалки" https://electrotransport.ru/index.php?msg=1669651

Alex_N

Я как считаю. Если ты утверждаешь, что что то можно сделать лучше, так покажи. Зачем просто так по клавишам молотить.
Тем более 2-3 строчки кода никак не раскроют секретного алгоритма. Нет, лучше всех грязью поливать.
И вот ещё. Был такой случай у меня. 16 лет назад мы с приятелем ( свято верующим в С++ ) решили определить, насколько по скорости Паскаль уступает С. Написали две одинаковые программы по вычислению миллионов синусов на Delphi и Builder-е соответственно и на одном и том же компьютере. Так приятеля чуть инфаркт не стукнул, когда выяснилось, что С проиграл в 2 раза. Не всегда прописные истины срабатывают.

bones

Цитата: mr.Dream от 15 Фев. 2018 в 14:08Это всего лишь контроллер заряда
Согласен, здесь нет смысла выставлять частоты дискретизации десятки или сотни килогерц, т.к. это связано с большими накладными расходами как на внешнюю обвязку АЦП, так и на программу.
Думаю каждый 2-й ставит на вход RC-фильтр, и чем больше частота преобразования, тем больше должно быть С и, соответственно, меньше R, а чтобы получить маленькое R нужен буферный ОУ, причем не LM358, а что-то посерьезнее.
Для оцифровки тока и напряжения, на мой взгляд, достаточно 10-100-1000 Гц. (Тау RC-фильтра делаем в 10 раз меньше периода опроса АЦП - это главный секрет :)
Цитата: UriBas от 15 Фев. 2018 в 14:34Хорошо бы примерчик с кодом
На ардуине ми не можем завести таймер на высокую частоту и подключить его выход к триггеру АЦП, или заставить АЦП писать напрямую в память без участия ядра МК, поэтому привести пример, в рамках данной темы, несколько проблематично, да и не нужно, думаю лучше сосредоточиться на алгоритмах.

Necromant

Доброго времени суток!

Предлагаю свой вариант простейшей моргалки с элементами адаптивного алгоритма.

Я моргаю обычным трансформаторным выпрямителем: 2 трансформатора ТН180 (выход 12,6В), диодный мост, конденсатор на 2200 мкФ. К выводам аккумулятора подключаю клеммы от зарядного и крокодилами моргалку, причем стараюсь чтобы клемма зарядного не касалась крокодила, был контакт только через вывод аккумулятора. Питание моргалки по USB от зарядника для мобильника. Выпрямитель подключен через твердотельное реле, применены обычные провод с вилкой и розетка.

Про моргалку:
Делитель напряжения из тех номиналов, что были под рукой. Massduino выбрано именно из-за 16-битного АЦП.  Можно использовать и 12-битные.

Калибровка заключается в определении отсчета 0В (U0 при замкнутых крокодилах) и пары-тройки точек для определения наклона линейной характеристики делителя + АЦП (он отличается от чисто расчетного)  и вычисление коэффициента maxV (соответствует отсчету 65535) .

Цена вопроса: контроллер 130 руб, реле SSR-10DA 150 руб, крокодилы 8 руб, резисторы, вилка с розеткой из запасов.

Программа:
Спойлер
#define maxV 18650   //  R1=10.00 kOhm  R2=1.52 kOhm
#define U0 1033
#define UpLimit 14400
#define dU 1
#define dUDrop 10
#define DropU 12000
#define DropTime 1000
#define ChargeTime 500
#define RelaxTime 2000
#define MeasureCount 4
#define VoltmeterPin A7
#define ChargeRelayPin 2
#define InternalLedPin 13

// Переменные
uint16_t U1;
boolean Flag14V4 = false;
//Функции
uint16_t ReadU (uint8_t Pin) //Вольтметр
{
  uint32_t S = 0,
           SumU = 0;
  uint8_t j = 0;
  struct MeasuredValue
  {
    uint16_t Value;
    int16_t Delta;
  } U[MeasureCount];
  for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Считаем среднее арифметическое
  {
    U[i].Value = analogRead_16bits(Pin);
    SumU += U[i].Value;
  }
  SumU = SumU / MeasureCount;
  for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Считаем среднеквадратическую погрешность
  {
    U[i].Delta = SumU - U[i].Value;
    S +=  sq(U[i].Delta);
  }
  S = sqrt( S / (MeasureCount - 1));
  SumU = 0;
  for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Отсеиваем промахи
  {
    if (abs(U[i].Delta) <=  3 * S)
    {
      SumU += U[i].Value;
      j++;
    }
  }
  SumU = SumU / j;
  SumU = map(SumU, U0, 65535, 0, maxV);
  return SumU;
}
//Процедуры
void relax(uint16_t Delta) //Адаптивная пауза
{
  uint16_t U2;
  do
  {
    U1 = ReadU(VoltmeterPin);
    delay (RelaxTime);
    U2 = ReadU(VoltmeterPin);
  }
  while ((U1 - U2) >= Delta);
}
void relayON()
{
  digitalWrite(ChargeRelayPin, HIGH);
  digitalWrite(InternalLedPin, LOW);
}
void relayOFF()
{
  digitalWrite(ChargeRelayPin, LOW);
  digitalWrite(InternalLedPin, HIGH);
}
//Инициализация
void setup()
{
  analogReference(INTERNAL2V56);
  pinMode(ChargeRelayPin, OUTPUT);   //SSR-10DA
  pinMode(InternalLedPin, OUTPUT);  //LED
  pinMode(VoltmeterPin, INPUT);    //Voltmeter
  delay(500);
}
//Цикл
void loop()
{
  U1 = ReadU(VoltmeterPin);
  while (U1 <= DropU) // Капельница до 12В снизу
  {
    U1 = constrain(U1, 10000, DropU);
    relayON();
    delay (map(U1, 10000, DropU, DropTime, 2000));
    relayOFF();
    relax(dUDrop);
    U1 = ReadU(VoltmeterPin);
  }
  if (!Flag14V4)  // Заряд по Вудбриджу до касания 14,4В сверху
  {
    while (U1 <= UpLimit)
    {
      uint32_t Timer, ChargePeriod;
      Timer = millis();
      relax(dU);
      Timer = millis() - Timer;
      relayON();
      Timer = constrain(Timer, 1000, 600000);
      ChargePeriod = int(pow(2.72, (13200. - U1) / 1000) * Timer + ChargeTime);
      Timer = millis();
      while ((U1 <= UpLimit) && ((millis() - Timer) <= ChargePeriod) )
      {
        U1 = ReadU(VoltmeterPin);
      }
      relayOFF();
    }
  }
  Flag14V4 = true;
  if (U1 >= UpLimit)   // Добивка
  {
    relayOFF();
    relax(dU);
  }
  else
  {
    relayON();
    delay (ChargeTime);
    while (U1 <= UpLimit)
    {
      U1 = ReadU(VoltmeterPin);
    }
  }
}

Калибровка:
Спойлер
#define maxV 18650 // 2560*(1+R1/R2) R1=10.00 kOhm R2=1.52 kOhm
#define U0 1025
#define MeasureCount 4
#define VoltmeterPin A7
#define InternalLedPin 13

// Переменные
uint16_t U1;

//Функции
uint16_t ReadU (uint8_t Pin)
{
uint32_t S = 0,
SumU = 0;
uint8_t j = 0;
struct MeasuredValue
{
uint16_t Value;
int16_t Delta;
} U[MeasureCount];

for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Считаем среднее арифметическое
{
U[i].Value = analogRead_16bits(Pin);
SumU += U[i].Value;
}
SumU = SumU / MeasureCount;
//Serial.println(SumU);
for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Считаем среднеквадратическую погрешность
{
U[i].Delta = SumU - U[i].Value;
S += sq(U[i].Delta);
}
S = sqrt( S / (MeasureCount - 1));
//Serial.println(S);
SumU = 0;
for (uint8_t i = 0; i <= (MeasureCount - 1); i++)// Отсеиваем промахи
{
// Serial.println(abs(U[i].Delta));

if (abs(U[i].Delta) <= 3 * S)
{
SumU += + U[i].Value;

//Serial.println(U[i].Value);
j++;
}
}
//Serial.println(j);
//Serial.println(SumU);
SumU = SumU / j;
Serial.println(SumU);
//Serial.println(j);
SumU = map(SumU, U0, 65535, 0, maxV);
//Serial.println();
return SumU;
;
}

//Инициализация
void setup()
{
analogReference(INTERNAL2V56);
pinMode(InternalLedPin, OUTPUT); //LED
pinMode(VoltmeterPin, INPUT); //Voltmeter

Serial.begin(9600);
}
//Цикл
void loop()
{
U1 = ReadU(VoltmeterPin);
Serial.println(U1);
Serial.println();
delay(1000);
}

Схема:
Спойлер

Alex_N

Интересно, а надолго ли хватит БП. А вообще решение нестандартное. Но невозможно применять всякие вещи, например модуляцию 2кГц.

Alex_N


Соединил БП от ноута HP 18.5В 6,5А с xl4016e1 в одном корпусе получилась неплохая штука.

ИС-Х

Цитата: Alex_N от 20 Фев. 2018 в 06:38Интересно, а надолго ли хватит БП.
Наверное надолго, ибо твердотелка с зеро-кросс - включается в момент перехода фазы через ноль.
Цитата: Alex_N от 20 Фев. 2018 в 06:38невозможно применять всякие вещи, например модуляцию 2кГц.
А оно надо?
Моя первая моргалка: https://electrotransport.ru/index.php?msg=588520
Вторая моргалка: https://electrotransport.ru/index.php?topic=31184.0
Третья моргалка: https://electrotransport.ru/index.php?msg=1130718
Еще в багажнике валяется BL1204 на всякий пожарный...

Necromant

Модуляция 2 кГц аккумулятору совершенно не нужна. На макроуровне аккумулятор очень медленное устройство, со временем отклика более сотых долей секунды. Если очень сильно хочется отслеживать наносекундные процессы на микроуровне, рекомбинацию каждого иона в электролите на границе с пластиной, то проще всего смотреть по рассеиванию пучка протонов. Так как это довольно энергозатратный процесс, можно открыть здесь отдельные темы про домашние атомные электростанции средней мощности и адронные коллайдеры в масштабе огорода.

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

KIE

Цитата: Necromant от 20 Фев. 2018 в 10:54Так что выбросов эдс самоиндукции не должно быть ну и снаббер вроде как есть.
Дело не в выбросах самоиндукции.
С индуктивной нагрузкой проблемы в экста токах пускового режима. По этому в паспорте на тв.тел. реле и не рекомендуется работа с индуктивной нагрузкой. Пуск трансф-ра при переходе фазы через ноль- самый опасный и не оптимальный режим.
Но в данной конструкции мощность реле превышает  мощ-ть нагрузки, работать будет.

Necromant

#863
Да, реле выбрано специально с большим запасом еще и по причине того, чтобы не устанавливать его на дополнительный радиатор.

Вообще в голове есть обрывки мыслей как заставить эту моргалку управлять переделанным компьютерным БП испльзуя 2 полноценных 10-ти битных ЦАП на борту, но пока они никак не хотят сложиться в стройную идею.

В ближайшее время дополню моргалку антикапельницей с двуканальной нагрузкой: разряд до касания напряжения разряда лампами 21+55 Вт, далее выкачка только лампой 21 Вт. Это для КТЦ моего зомби Медалист 55Ач предположительно 2005 г.в. Заболел он на машине 2 года назад и поехал умирать в ИБП.