Помогите подправить код эмулятора датчиков двигателя
- Войдите на сайт для отправки комментариев
Ср, 05/05/2021 - 14:46
Суть процесса:два вывода формируют импульсы и связаны между собой временными зависимостями(фазой).
KW формирует импульсы по формуле 60-2, ну а NW привязан числу импульсов.
хочется "управлять фазой"
В моем скетче это сделано с шагом в 1 импульс по выводу KW, что не отвечает плавности.( хочется смещать плавно в диапазоне, например 5 импульсов.
Подскажите идею как это реализовать? чувствую дело идет к таймерам и прерываниям...но что-то в голову не приходит идея...
И еще:
Можно ли тот код , который уже есть, привести к " двум строкам"?
#define KW 7
#define NW 6
#define str 5
#define pot A1
uint16_t rpmtime = 160;
uint16_t valpot,cor=0;
void setup() {
pinMode(KW, OUTPUT);
pinMode(NW, OUTPUT);
pinMode(str, OUTPUT);
pinMode(pot, INPUT);
digitalWrite(NW, LOW);
digitalWrite(KW, LOW);
digitalWrite(str, LOW);
}
void loop() {
valpot = analogRead(pot);
cor = map(valpot, 0, 1024, 0, 6);
for ( int i = 0; i < 119; i++) {
if (i==1){digitalWrite(str, HIGH);}
if (i == (12 + cor)) {
digitalWrite(NW, HIGH);
}
else if (i == (20 + cor)) {
digitalWrite(NW, LOW);
}
else if (i == (26 + cor)) {
digitalWrite(NW, HIGH);
}
else if (i == (50 + cor)) {
digitalWrite(NW, LOW);
}
else if (i == (56 + cor)) {
digitalWrite(NW, HIGH);
}
else if (i == 58 ) {
digitalWrite(str, LOW);
noimpulse();
i++;
}
else if (i == (80 + cor)) {
digitalWrite(NW, LOW);
}
else if (i == (102 + cor)) {
digitalWrite(NW, HIGH);
}
else if (i == (110 + cor)) {
digitalWrite(NW, LOW);
}
else if (i == 118) {
noimpulse();
i++;
}
impulse();
}
}
void impulse() {
digitalWrite(KW, HIGH);
delayMicroseconds(rpmtime);
digitalWrite(KW, LOW);
delayMicroseconds(rpmtime);
}
void noimpulse() {
delayMicroseconds(rpmtime);
delayMicroseconds(rpmtime);
delayMicroseconds(rpmtime);
delayMicroseconds(rpmtime);
}
Переход от делеев к микрос() и миллис() откроет перед вами воистину новые горизонты
Можно ли тот код , который уже есть, привести к " двум строкам"?
Легко!
// код, который уже есть, приведённый к " двум строкам"? constexpr uint8_t KW=7,NW=6,str=5,pot=A1; uint16_t rpmtime = 160,valpot,cor=0; void setup() { pinMode(KW, OUTPUT); pinMode(NW, OUTPUT); pinMode(str, OUTPUT); pinMode(pot, INPUT); digitalWrite(NW, LOW); digitalWrite(KW, LOW); digitalWrite(str, LOW); } void loop() { valpot = analogRead(pot); cor = map(valpot, 0, 1024, 0, 6); for ( int i = 0; i < 119; i++) { if (i==1){digitalWrite(str, HIGH);} if (i == (12 + cor)) { digitalWrite(NW, HIGH); } else if (i == (20 + cor)) { digitalWrite(NW, LOW); } else if (i == (26 + cor)) { digitalWrite(NW, HIGH); } else if (i == (50 + cor)) { digitalWrite(NW, LOW); } else if (i == (56 + cor)) { digitalWrite(NW, HIGH); } else if (i == 58 ) { digitalWrite(str, LOW); noimpulse(); i++; } else if (i == (80 + cor)) { digitalWrite(NW, LOW); } else if (i == (102 + cor)) { digitalWrite(NW, HIGH); } else if (i == (110 + cor)) { digitalWrite(NW, LOW); } else if (i == 118) { noimpulse(); i++; } impulse(); } } void impulse() { digitalWrite(KW, HIGH); delayMicroseconds(rpmtime); digitalWrite(KW, LOW); delayMicroseconds(rpmtime); } void noimpulse() { delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); }Ровно две строки! :-)
Да... это мой уровень....надеюсь, пока...
Я построил его на понятных мне функциях.
Предполагаю, что существуют другие более лаконичные способы, с которыми я бы хотел познакомится.
если можно дайте намек или ссылочку. но только не такую короткую ка milis() micros()
мне пока не понятно, как обработать не периодичный сигнал этими функциями
Вот осциллограмма сигналов
Я сам ниразу не великий программист и захожу сюда почерпнуть что-нибудь интересное для себя, но вопрос топика ввел меня в ступор. Понять чего хочет автор очень сложно, возможно для автора это не проблема ему то самому все ясно, но кто возьмется разгадать один ребус в описательной части и потом понять чего автор добивался в своей программе. Есть поговорка: " Каков вопрос таков ответ"
Благодарность от автора ... ну, Вы сами видите.
Потому, я даже пытаться не буду выяснять что ему нужно по другому вопросу. Зачем, если ему даёшь готовое решение, а ему даже "спасибо" сказать в лом?
Извините, что не правильно излагаю свои мысли. Я привел осциллограмму для лучшего восприятия моего вопроса )
ЕвгенийП, я очень даже благодарный. Просто мне показалось, что Вы меня троллите и так принято на форуме... после чего я приложил картинку.
Под термином "фаза", подразумевается смещение одного сигнала относительно другого.
#define KW 7 #define NW 6 #define str 5 #define pot A1 uint16_t rpmtime = 160; uint16_t valpot,cor=0; void setup() { pinMode(KW, OUTPUT); pinMode(NW, OUTPUT); pinMode(str, OUTPUT); pinMode(pot, INPUT); digitalWrite(NW, LOW); digitalWrite(KW, LOW); digitalWrite(str, LOW); } void loop() { valpot = analogRead(pot); // считываем желаемое смещение сигналов cor = map(valpot, 0, 1024, 0, 6); // извлекаем полученное смещение сигналов for ( int i = 0; i < 119; i++) { // создаем цикл для эмуляции двух оборотов коленвала if (i==1){digitalWrite(str, HIGH);} if (i == (12 + cor)) { //задаем начальное смещение сигналов + желаемое digitalWrite(NW, HIGH); } else if (i == (20 + cor)) { digitalWrite(NW, LOW); } else if (i == (26 + cor)) { digitalWrite(NW, HIGH); } else if (i == (50 + cor)) { digitalWrite(NW, LOW); } else if (i == (56 + cor)) { digitalWrite(NW, HIGH); } else if (i == 58 ) { // если это 58 импульс, то пауза в 2 импульса digitalWrite(str, LOW); noimpulse(); i++; } else if (i == (80 + cor)) { digitalWrite(NW, LOW); } else if (i == (102 + cor)) { digitalWrite(NW, HIGH); } else if (i == (110 + cor)) { digitalWrite(NW, LOW); } else if (i == 118) { // если это 118 импульс, то пауза 2 имульса noimpulse(); // далее по циклу i++; } impulse(); } } void impulse() { digitalWrite(KW, HIGH); delayMicroseconds(rpmtime); digitalWrite(KW, LOW); delayMicroseconds(rpmtime); } void noimpulse() { delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); delayMicroseconds(rpmtime); }Ни по коду, ни по картинке, ни по описанию не понятно, что же точно должно происходить.
Безусловно, согласен!
Но мне кажется, что профи достаточно просто взглянуть и все станет понятно что и как... Другое дело формальности...
Мне бы хотелось увидеть: Как иначе можно решить эту задачу ( передача аргументов в фукцию, массивы, micros, millis...?
И конечно реализовать плавное смещение сигналов ( не ступенчато)
Это не слишком много я прошу? )
Ни по коду, ни по картинке, ни по описанию не понятно, что же точно должно происходить.
Вы знакомы с системой управления ДВС?
Если да, то думаю поймете что я тут изображаю
Прочитал несколько раз. Так и не понял что должно зависить от количества импульсов и каких. Что такое формула 60-2 ? К числу импульсов чего привязан NW?
Начать описание надо было с того, кто выдает импульсы, кто считывает, кто от кого зависит и как. Даже знакомому с ДВС не понятно, что же нужно сделать.
Если бы я хотел создать временной сдвиг между некоторыми событиями я бы использовал конструкцию типа:
unsigned long time; unsigned long phase;//можно успешно изменять из других фрагментов программы .......... условие, например запуск базового импульса { time=millis();//можно micros() в зависимости от ситуации } if(millis()-time>phase) { запуск сдвинутого импульса; }Товарищи! Вы видимо не прочитали мое скудное описание вначале!
nik182 он должен знать эту формулу, если связан с диагностикой двс.
Таких подробных описаний я не видел ни у кого....
Есть система управления двс(блок). есть сам двигатель. на двигателе есть два вала коленчатый и распределительный. они связаны между собой приводом с передаточным отношением 2/1 , т.е на два оборота коленвала(КВ) - один оборот распредвала(РВ). на валах закреплены импульсные диски. На коленвале диск имеет 58 зубов и 2 пропуска (60-2), на распредвале 4 зуба разной ширины.
датчики передают сигналы в блок. все крутится по кругу..(назовем это в цикле) С условного "старта" , например пропуска в два зуба, должно пройти 12 импульсов с диска КВ, должен смениться сигнал с датчика РВ.потом через 6 зубов, потом через 24 итд...и прийти опять к началу. нужно эмулировать двигатель с валами. при этом необходимо менять смещение сигналов после условного старта, в+-...
Скетч работает! но мне не нравится что он изменяет смещение целым зубом(импульсом).
Я решения пока не вижу .
Alexey_Rem, спасибо, буду обмозговывать это...
фазу действительно можно плавно менять через миллис, но как к этому привязать и длительность импульса и пропуски в два зуба и непериодичный сигнал РВ.
Если у кого-то есть решение задачи и его это не обременит, то пусть покажет как иначе сделать... для общего развития. Спасибо.
Нет, не знаком. Я программист, а не механик.
Нет, не знаком. Я программист, а не механик.
тонкости механики конечно важны, но я привел осциллограмму для более точного понимания.
неужели в моем говнокоде, Вам не понятно что я там делаю?
Я бы написал два фрагмента кода один генерирует сигнал с КВ другой с РВ и синхронизировал бы их выполнение с какой надо задержкой да и все тут
class Val { protected: const uint16_t * data; const uint8_t data_size; const uint8_t pin; uint8_t data_pos = 0; uint16_t phase_start = 0; public: template <uint8_t S> Val(const uint16_t (&data)[S], uint8_t pin): data(data), data_size(S), pin(pin) { pinMode(pin, OUTPUT); } // сдвиг по фазе изменять плавно. void loop(int16_t phase_shift = 0) { if (millis() - phase_start + phase_shift > data[data_pos]) { digitalWrite(pin, !digitalRead(pin)); data_pos++; if(data_pos == data_size) { phase_start += data[data_pos - 1]; data_pos = 0; } } } }; // интервалы отрезков. 50мс - 0, следующие 75 мс - 1, следующие 75 мс - 0, следующие 50 мс - 1 uint16_t p1[] = {50,125,175,225}; uint16_t p2[] = {50,100,150,200,250,300}; Val v1(p1, 2); Val v2(p2, 3); void setup(){}; void loop() { v1.loop(); v2.loop(-70); }Примерно так. Не тестировал.
Красиво
мы сподобились лицезреть код от rkit. Я в шоке.
Тока скажите ему уже чонить за Ctrl-T.
class Val { protected: const uint16_t * data; const uint8_t data_size; const uint8_t pin; uint8_t data_pos = 0; uint16_t phase_start = 0; public: template <uint8_t S> Val(const uint16_t (&data)[S], uint8_t pin): data(data), data_size(S), pin(pin) { pinMode(pin, OUTPUT); } // сдвиг по фазе изменять плавно. void loop(int16_t phase_shift = 0) { if (millis() - phase_start + phase_shift > data[data_pos]) { digitalWrite(pin, !digitalRead(pin)); data_pos++; if(data_pos == data_size) { phase_start += data[data_pos - 1]; data_pos = 0; } } } }; // интервалы отрезков. 50мс - 0, следующие 75 мс - 1, следующие 75 мс - 0, следующие 50 мс - 1 uint16_t p1[] = {50,125,175,225}; uint16_t p2[] = {50,100,150,200,250,300}; Val v1(p1, 2); Val v2(p2, 3); void setup(){}; void loop() { v1.loop(); v2.loop(-70); }Круто. Хотя не тестировал, но видна рука профессионала.
А чего ему плюсик не поставил? Завидуешь?
class Val { protected: const uint16_t * data; const uint8_t data_size; const uint8_t pin; uint8_t data_pos = 0; uint16_t phase_start = 0; public: template <uint8_t S> Val(const uint16_t (&data)[S], uint8_t pin): data(data), data_size(S), pin(pin) { pinMode(pin, OUTPUT); } // сдвиг по фазе изменять плавно. void loop(int16_t phase_shift = 0) { if (millis() - phase_start + phase_shift > data[data_pos]) { digitalWrite(pin, !digitalRead(pin)); data_pos++; if(data_pos == data_size) { phase_start += data[data_pos - 1]; data_pos = 0; } } } }; // интервалы отрезков. 50мс - 0, следующие 75 мс - 1, следующие 75 мс - 0, следующие 50 мс - 1 uint16_t p1[] = {50,125,175,225}; uint16_t p2[] = {50,100,150,200,250,300}; Val v1(p1, 2); Val v2(p2, 3); void setup(){}; void loop() { v1.loop(); v2.loop(-70); }Примерно так. Не тестировал.
Просто стою и уважительно смотрю в Вашу сторону!
Спасибо Большое. позднее зашью, проверю,отпишусь. и буду изучать Ваш код.
Уточните пожалуйста какие пины задействованы на выход ( 2 и 3 я так понимаю) и входной пин не учавствует?
А другие алгоритмы существуют? Более понятные, так сказать неофиту...
Присоединяюсь. Автору кода-если не трудно (жалко) киньте ссылочку где почитать об ООП доступно
rkit, если у Вас будет время. прокомментируйте пожалуйста, где переменная скорости вращения( скорости прохождения LOOP).
мне что то подсказывает, что она здесь постоянная.
Пропал дом :-)
Согласен за дом. Любой написанный новичку код (правильный или не очень) безнаказанным не остаётся.
Вы опять с кучкой бесполезных комментариев? Ну ни в одной теме от Вас ничего хорошего не видел.
rkit, не подумайте, что я к Вам с претензией. Спасибо Вам большое ! дали пищу для размышлений.
код опробовал, есть нюансы. хотел бы задать вопрос по теме.
Подскажите, на этом ресурсе есть возможность задавать вопросы лично?
Есть два встречных вопроса:
1) какие темы Вы читали?
2) где на этом форуме можно ознакомиться с Вашими хорошими и полезными комментариями?
class Val { protected: const uint16_t * data; const uint8_t data_size; const uint8_t pin; uint8_t data_pos = 0; uint16_t phase_start = 0; public: template <uint8_t S> Val(const uint16_t (&data)[S], uint8_t pin): data(data), data_size(S), pin(pin) { pinMode(pin, OUTPUT); } // сдвиг по фазе изменять плавно. void loop(int16_t phase_shift = 0) { if (millis() - phase_start + phase_shift > data[data_pos]) { digitalWrite(pin, !digitalRead(pin)); data_pos++; if(data_pos == data_size) { phase_start += data[data_pos - 1]; data_pos = 0; } } } }; // интервалы отрезков. 50мс - 0, следующие 75 мс - 1, следующие 75 мс - 0, следующие 50 мс - 1 uint16_t p1[] = {50,125,175,225}; uint16_t p2[] = {50,100,150,200,250,300}; Val v1(p1, 2); Val v2(p2, 3); void setup(){}; void loop() { v1.loop(); v2.loop(-70); }Примерно так. Не тестировал.
интересный код. И даже компилируется :)
Любопытно, компилятор сам определяет размер переданного конструктору массива и подставляет в парметр шаблона? - не видел такого прежде, обычно вроде шаблону явно надо указывать
1 Те, которые создавал. Вы в них особо отличились.
Прочие сейчас указывать не буду искать нужно, но Ваше отношение ко мне и другому числу новичков - очевидно. Причем, язвительность Ваших утверждений указывает на крайнюю нетерпимость к начинающим.
2 Вы знаете мой уровень.
Вопрос по теме:
Вот в этой строчке
:uint16_t p2[] = {50,100,150,200,250,300};
здесь формируется 6 имульсов длительностью 50 мс но у по условию их должно быть 120 - 4.
как можно оптимизировать массив прописав туда (58 импульсов+2 пропуска+ 58 импульсов+2 пропуска)
не проставлять же тайминги для 120...
Вопрос по теме:
Вот в этой строчке
:uint16_t p2[] = {50,100,150,200,250,300};
здесь формируется 6 имульсов длительностью 50 мс но у по условию их должно быть 120 - 4.
как можно оптимизировать массив прописав туда (58 импульсов+2 пропуска+ 58 импульсов+2 пропуска)
не проставлять же тайминги для 120...
в этом коде придется проставлять тайминги. Если два цикла 58+2 абсолютно одинаковы, то не вижу смысла описывать 120. хватит и 60-ти. Но 60 прописывать придется.
Чтобы не прописывать 58 одинаквых импульсов, код нужно несколько изменить, например добавить счетчики для равных интервалов. Но сейчас, повторяю, в этом коде этого нет.
...киньте ссылочку где почитать об ООП доступно
Скину сылочку, может понравится, только старожилам меня не выдавайте.
https://www.youtube.com/watch?v=ULpr1Z0WEtQ&list=PLQOaTSbfxUtCrKs0nicOg2npJQYSPGO9r&index=87
Спасибо, в текстовом виде ( я так лучше понимаю), в принципе с примитивными классами все понятно а вот вопросы использования структур, указателей, ссылок и т. д. хотелось бы изучить подробнее, хотя скорее это Си а не только ООП.
в этом коде придется проставлять тайминги. Если два цикла 58+2 абсолютно одинаковы, то не вижу смысла описывать 120. хватит и 60-ти. Но 60 прописывать придется.
Чтобы не прописывать 58 одинаквых импульсов, код нужно несколько изменить, например добавить счетчики для равных интервалов. Но сейчас, повторяю, в этом коде этого нет.
[/quote]
Спасибо, b707.
Почему -то через 1мин 06 сек программа перестает работать и МК начинает генерить меандр по обоим пинам с периодом 27мкс..? что это может быть? проверил несколько раз
Почему -то через 1мин 06 сек программа перестает работать
что это может быть?
переполнение в 15 строке,
65536 мс = 65.5 сек = 1 мин 5.5 сек
переполнение в 15 строке,
65536 мс = 65.5 сек = 1 мин 5.5 сек
Ух ты, блин! А я так с ходу и не заметил!
Блин, вот смотришь на форум - ну насколько же правильно всё на лурке описано. Я часто цитирую про то, как посылают "исключительно из добрых побуждений", а там ведь и продолжение - как раз про нынешний случай: "Тролли же с удовольствием дают исходники, радостно наблюдая как стремительно фалломорфируют просящие (да и кто обещал рабочие исходники?)" :-)
"Тролли же с удовольствием дают исходники, радостно наблюдая как стремительно фалломорфируют просящие (да и кто обещал рабочие исходники?)" :-)
обязательно "тролли"?
По моему мнению коды, выкладываемые в таких ветках для новичков - предлагаются как пример, никто не гарантирует, что это готовый продакшен. Да и в данном случае автор специально предупредил, что код не проверен.
Вот если "гуру" вставляет ошибки в пример специально, чтоб потроллить новичка - это, считаю, некрасиво. А непреднамеренные опечатки или недостаточная проработка - это жизнь. Все мы ошибаемся.
По моему мнению коды, выкладываемые в таких ветках для новичков - предлагаются как пример, никто не гарантирует, что это готовый продакшен. Да и в данном случае автор специально предупредил, что код не проверен.
На сколько объективный у Вас взгляд на эти вещи. Я не ищу готового решения. но хочу понять ,как правильно это сделать. Как профи это видит.
Автор кода, к сожалению, не нашел времени на комментарий.
Может Вы, b707, подскажете?
Почему у функции V2.loop указан параметр(-70)? Что он делает?
И второй вопрос: Правильно ли я понимаю, если указать параметр phase_shift, то он ровным счетом ничего не изменит, потому что при обработке оба сигнала получат одинаковый сдвиг?
Почему у функции V2.loop указан параметр(-70)? Что он делает?
Об этом лучше спросить у автора. Но насколько я вижу, -70 - этот как раз тот сдвиг фазы, который Вам нужен.
Думаю неправильно. В коде описан класс Val и обьявлены два его экземпляра - V1 и V2. Поле phase_shift у каждого экземпляра свое, так что если их обьявить правильно, сдвиг будет разным.
Но вообще, судя по вопросу, вы этот код не понимаете совсем. Советую вам что-нибудь почитать про классы, так как иначе вам для понимания придется пересказать получебника
Спасибо, b707. Получается, что до объявления void setup создается прототип функции loop , который принимает знаковое значение phase_shift, а потом в теле цикла ему передается само значение? Как например в данном случае (-70)? А переполнение в 15 строчке возникает только из-за того что параметр phase_start имеет тип uint16_t? а если он будет uint32_t такого не возникнет? Или возникнет, но не скоро?
переполнение в 15 строчке возникает только из-за того что параметр phase_start имеет тип uint16_t? а если он будет uint32_t такого не возникнет? Или возникнет, но не скоро?
правильно. В случае если параметр будет иметь тип uint32_t, переполнение случится не скоро, через 49 дней. Но, главное, поскольку счетчик миллис тоже имеет тип uint32 - они переполнятся одновременно и это переполнение не будет иметь никаких последсткий для программы - код продолжит работать без ошибок и после этого времени.
обязательно "тролли"?
В данном случае - 101 пуд! Дело даже не в ошибке. Вы на код посмотрите. И на активность автора в его разъяснении :-)
А что значит, когда в шаблоне имя берется в такие кавычки < имя> ?
Здесь, например <uint8_t S>.
Я просматривал уроки по классам, там не было таких примеров
ТС - задача твоя решается очень просто.
Делаешь процедуру, которая берёт из массива булевы данные с датчиков ( 0 или 1)
Это будет единичный квант времени, 360 квантов = одному обороту коленвала.
А управлять фазой по распредвалам уже будешь смещением счётчика, бегающего по массива распредвала.
Подобная задача уже решалась здесь, несколько месяцев назад.
Единственная проблема - не хватает скорости проца, больше 1500 об/мин у меня не получилось сделать.
Выход - переход на стм32.
Не припомните, по каким меткам (словам) искать?
хочется на код взглянуть - жадный, так сказать до кода :)
Кода нет на форуме, он коммерческий. Посему можешь не искать.
Приведенный мной код корректно обрабатывает переполнение переменных, и проработал 10 минут без проблем. В тему не заглядывал, потому что знал, что набегут бесноватые, и предпримут всё возможное, чтобы попортить мне нервы. Буду продолжать не заглядывать.
rkit, огромное спасибо за идею и потраченное время!
Чтобы не быть голословным приведу тоже фото переходного процесса:
Куда все пропали?
15 строчку заменить на if ((uint16_t)millis() - phase_start + phase_shift > data[data_pos]) {