avatar_UriBas

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

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

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

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

Dunkel

Цитата: Dkin от 21 Март 2017 в 22:40
Получается, если напряжение превысило - пауза,
если нет - просто перепрыгиваем паузу

Все-таки не нравятся мне перепрыгивания, потом запутаемся.
Может просто заканчивать цикл:

for (int i=0; i <= n; i++) {
  digitalWrite(1, HIGH);
  delay(imp); 
  U = analogread (A0)
  if u>14,4   i = n;  flag = 1;  - закончили цикл, подняли флаг
  digitalWrite(1, LOW);
  delay(pause);
}
Многофункциональная облачная моргалка/логгер:
https://morgalka78.wordpress.com/

Dkin

Работать будет в обоих случаях. Думаю сделаю свой крайний вариант, настрою, выложу все в первый пост с подробным описанием и на этом останавливаться. До адаптивного варианта очень далеко, да и нужен ли он в простой моргалке?
Кто захочет - пусть продолжит.

реношник


Dkin

#57
Хороший результат. Я конечно же понял только первые три строчки из модифицированного кода. Не могли бы вы подсказать как написать такой код применительно только к А0 и D10, D12, D13, которые мы используем здесь. Но даже со стандартными временами для наших целей пойдет.

Яков93

Оно конечно классно, аж 100 мкс на одной операции чтения экономится. Это если делать 10 выборок подряд съэкономим целую 1 миллисекунду (delay(1)), которую потом можно использовать... елки, даже не придумаю куда ее можно использовать в обычной моргалке с частотой моргания 35 Гц и паузами по 10 секунд.
Я вот честно, уважаю таких крутых спецов как Реношник, по мне, так это высший пилотаж реально  :wow:
Но начинать надо с чего-то простого, то что по-сложнее потом само придет если еще желание программировать не пропадет.

Dkin

Ой, а я посчитал сходу, что экономится секунда и расстроиться успел уже. Если 1 мс, то и заморачиваться не стоит, если это так, с нашими уровнями частот.  Программа вообще-то позиционируется как для новичков, чтобы изучить смогли и под себя подстроить. С обычным кодом гораздо нагляднее.

mr.Dream

Мне когда влом писать "многобуков", использую "аналогРид", но если "стандартные" настройки регистров удовлетворяют, памяти свободной многого время выполнения операции (как в этом случае) некритично.
Если хотите, чтобы во время паузы в 30 секунд что то еще могло выполняться, откажитесь от длинных delay, запоминайте текущее время в переменную + длина паузы, и сравнивайте с текущим. используйте логические операторы и/или в условиях
msPrevious = millis();
if(((msPrevious + 30000) < millis()) & ((analogRead(A0) * coeficient) < 14.4)){
что то делаем или не делаем;
delay(1); //1 милисекунда не критична, или вместо нее в цикле куча АЦПреобразований, чтобы не пустовало :)
}

со временем, когда будет приходить познание, digitalWrite(13, HIGH) будете менять на PORTB = PORTB | (1 << PB5)
или PORTB |= (1 << PB5), или PORTB |= 0b00100000, что то же самое для компилятора, только ипользуются унарный оператор.

А пока что делайте так, чтобы было самому понятно. Места и быстродействия для ваших задач хватить на стопицот моргалок :)

Alex_Soroka

Цитата: реношник от 22 Март 2017 в 19:10
:bw:   https://www.drive2.ru/b/468551383692346485/
ну так правильно - программировать надо ГОЛОВОЙ а не задним местом!  B-)
тогда и процессор дурной работы лишней не будет делать.  :hello:

Dunkel

Да не обращайте внимание, есть такой старый анекдот: Почему нельзя изнасиловать женщину на пляже? - советами замучают.
Лучше скажите, зачем на схеме нарисован конденсатор в делителе?
Мы же вроде импульсы хотим измерять.
Многофункциональная облачная моргалка/логгер:
https://morgalka78.wordpress.com/

UstAlexei

[user]Dunkel[/user], дабы от случайного шума избавиться, можете не ставить, работать будет и без него. Та емкость и то сопротивление вносят свою задержку, назовем
постоянную времени этой задержки t (тау), (4 - 5)*t приведет к тому что переходный процесс практически закончится, т.е. не будет иметь влияния на измерения, а вот от шума более высокочастотного избавит.

Dunkel

[user]UstAlexei[/user],
Я думал, для избавления от шума мы делаем несколько измерений, а потом усредняем.
Или это разные вещи?
Многофункциональная облачная моргалка/логгер:
https://morgalka78.wordpress.com/

UstAlexei

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

Dkin

Значит, движемся мы в правильном направлении!

Dkin

Протестировал крайнюю версию программы. Исправил ошибки, которые сразу выдала ардуино. На вход А0 подавал пока абстрактное напряжение 5В. При его появлении заряд уходит в отсечку, как и планировалось. Остается разобраться с усреднением AnalogRead, переводом напряжения в 14,4В.

Спойлер

// Общие настройки - Несущая частота
float freq = 35.00; // частота в Гц (от 1 до 350)
float skv1 = 50.00; // коэффициент заполнения (от 1 до 99)

// 1 этап Модулирующие импульсы
long zar1 = 30; // время заряда в сек (от 1 сек)
long pauseosn1 = 10; // время паузы в сек (от 1 сек)

// 2 этап работа отсечки
long Uots = 690; // напряжение отсечки 690 - пока для примера (допустим 690 в пересчете с делителя напр. 14,4 В)
long pauseots1 = 60; // время паузы в сек (от 1 сек)

float impnes1 = 0.00;
float pausenes1 = 0.00;
long previousMillis = 0;
long Utek = 0;

void setup()
{
   pinMode(13, OUTPUT); // используем 13 выход для управления ключом, на нем также висит синий светодиод, располагающийся на плате, для наглядности
   pinMode(10, OUTPUT); // светодиод отсечка
   pinMode(12, OUTPUT); // светодиод заряд
   pinMode(0, INPUT); // вход A0 с делителя напряжения

   impnes1 = 10 * skv1 / freq; // расчет импульса заряда несущей частоты
   pausenes1 = 10 * (100 - skv1) / freq; // расчет паузы несущей частоты
}

void loop()
{
// расчет основного цикла заряд/пауза
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > zar1*1000) // если время заряда истекло
{
    digitalWrite(13, LOW); // выключаем ключ
    digitalWrite(12, LOW); // гасим светодиод заряд
    delay (pauseosn1*1000);
    currentMillis = millis();
    previousMillis = currentMillis;
}
// работа импульсов несущей частоты
  digitalWrite(12, HIGH); // включаем светодиод заряд
  digitalWrite(13, HIGH); // включаем ключ
  delay(impnes1 );                     
  Utek = analogRead(0); //измеряем напряжение на входе A0
  if (Utek > Uots) // если измеренное напряжение больше напряжения отсечки
{
goto label1; // перейти на паузу отсечки
}
  digitalWrite(13, LOW); // отключаем ключ
  delay( pausenes1 );
  goto label2; // пропустить паузу отсечки
label1:
    digitalWrite(13, LOW); // выключаем ключ
    digitalWrite(12, LOW); // гасим светодиод заряд
    digitalWrite(10, HIGH); // включаем светодиод отсечка
    delay (1000);
    digitalWrite(10, LOW); // гасим светодиод отсечка
    delay (pauseots1*1000-1000); //пауза после отсечки минус 1 сек (горение светодиода отсечка)
    currentMillis = millis();
    previousMillis = currentMillis;
label2:
delay( 1 );
}

Dkin

При постоянном удержании на входе А0 напряжения 5В проходит один импульс заряда и уход в паузу отсечки (60 сек) и так по кругу. Без напряжения на входе А0 моргалка работает 30/10 сек как обычно.

Dunkel

Тоже провел натурные испытания, только уже на реальной зарядке и АКБ.
АКБ заряжается, отсечка работает.
Теперь надо уточнить по алгоритму, я сделал так - при касании 14,4В цикл зарядных импульсов прерывается, пауза увеличивается, длительность заряда уменьшается. Так до 10 касаний, потом переход на добивку.
Наверное, это надо подкорректировать, готов выслушать предложения.

// Digispark Attiny85

int zar = 30 ; //Большой цикл - заряд в сек
int raz = 10 ; //Большой цикл - пауза в сек
int imp = 14 ; //Малый цикл - импульс в мсек
int pause = 14 ; //Малый цикл - пауза в мсек
int n = zar * 1000 / (imp + pause) ; //Кол-во малых циклов в большом
int flag = 0; //Счетчик касаний 14,4В
int U = 0;   
void setup() {               
  pinMode(1, OUTPUT); //P1 Digispark
}
void loop() {
if (flag < 10) //Стадия заряда до 10 касаний 14,4В
{
for (int i=0; i <= (n - flag); i++) { //Уменьшаем заряд при касании 14,4В
  digitalWrite(1, HIGH);
  delay(imp); 
  digitalWrite(1, LOW);
  delay(pause-5); //5мс на дальнейшие измерения
  U=0;
  for (int i=1; i<=10; i++) U+=analogRead(1);  //P2 Digispark
  U = U*0.242;  //коэффициент делителя подбирается индивидуально 
  if (U > 1440) { //Касание 14,4В
      i = n-flag; //Выходим из цикла
      flag = flag + 1; //Увеличиваем счетчик касаний 14,4В
   }
  }
delay((raz + flag) * 1000); //Увеличиваем паузу при касании 14,4В
}
else
{
  //Стадия добивки
}

}

Многофункциональная облачная моргалка/логгер:
https://morgalka78.wordpress.com/

Dkin

При каждом касании 14,4 В пауза увеличивается на 1 сек?

Dunkel

Многофункциональная облачная моргалка/логгер:
https://morgalka78.wordpress.com/