#1 2017-06-07 23:46:11

gorenkov
Учасник
З Кіев
Зареєстрований: 2015-11-05
Повідомлень: 41

Прошу помощи. Тензодатчик + шаговый двигатель

Здравствуйте,

Решил автоматизировать взвешивание у себя в мастерской. Для этих целей прикупил тензодатчик и модуль датчика весов + Arduino UNO. Проблема в следующем: когда закомментирована функция scales(); управление шаговым двигателем работает превосходно. Как только я раскомментирую scales(); - шаговый двигатель крутится со скоростью 1 шаг в минуту. Немного подправив scales(); мне удалось добиться вращения шагового двигателя порядка 1 шаг в секунду. Отсюда я сделал вывод что всю систему тормозит именно scales();.

Подскажите, пожалуйста, что я делаю не так? Как ускорить работу системы в целом? Заранее благодарен.


Скетч - с миру по нитке + свои мысли:

#include <HX711.h>    // Подключаем библиотеку HX711 для работы с АЦП hx711
#include <Stepper.h>  // Подключаем библиотеку шагового двигателя

HX711 scale(A2, A3);                                // Указываем в какие пины подключен АЦП hx711 (DT(DOUT)  - pin A1, SCK - pin A0)

float myScale;  // Инициализируем переменную в которой будем хранить текущий вес
boolean stringComplete = false;  // whether the string is complete
String serialData = "";
int serialDataInt;
int stopWeight = 400;
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution for your motorconst int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution for your motor
int stepperSpeed = 400;
int stepperDirection = -1;
int Speed;
int Direction;

Stepper myStepper(stepsPerRevolution, 2, 3);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);                               // Инициализируем монитор порта, как устройство вывода
  Serial.println("Calibration...");                 // Выводим надпись
  
  scale.set_scale(-202.13);                          // Устанавливаем калибровочный коэффициент 
  scale.tare();                                     // Сбрасываем весы на 0
  myScale = round(scale.get_units(10));             // Запоминаем среднее значение без груза, но с учетом тары 
  Serial.print("Scale: ");
  Serial.println(0.00);                             // Обнуляем значение веса на мониторе порта

}

void loop() {
    
  if (serialData == "f"){
//    Serial.println("forward");
    int Speed = 300;
    int Direction = -1;
    stepperMotor (Speed, Direction);
    }
    else if (serialData == "b"){
//    Serial.println("backward");
    int Speed = 300;
    int Direction = 1;
    stepperMotor (Speed, Direction);
    }
    else if (serialData == "s"){
//    Serial.println("stop");
    int Speed = 300;
    int Direction = 0;
    stepperMotor (Speed, Direction);
    }
    else if (serialDataInt > 0){
    stopWeight = serialDataInt; 
    Serial.print("stop weight: ");
    Serial.println(stopWeight);
    }
//  }

     if (stopWeight < myScale){    // we should stop motor
    Serial.println("OVER!!!");
    int Speed = 0;
    int Direction = 0;
    stepperMotor (Speed, Direction);
}

  scales();
 
}

void serialEvent() {

if (Serial.available() > 0) {
  serialData  = Serial.readStringUntil('\n');
  serialDataInt = serialData.toInt();
  }
}

void scales() {
    scale.power_up();  // Отключаем энергосберегающий режим hx711
    
    if (round(scale.get_units(10)) != myScale) {      // Условие выполняется, если округленный до граммов вес отличается от последнего
    myScale = scale.get_units(20);                  // Запоминаем текущий вес
   
    if (myScale > 0.5) {                             // Если вес не ничтожно мал
      Serial.println (myScale);                      // то выводим его
    }
    else {                                           // иначе
      Serial.println(0.00);                         // выводим нули
    }

    myScale = round(myScale);   
  }
}

void stepperMotor (int stepperSpeed, int stepperDirection) {
  myStepper.setSpeed(stepperSpeed);
  myStepper.step(stepperDirection);
  }

Остання редакція gorenkov (2017-06-07 23:47:21)

Неактивний

#2 2017-06-08 07:19:35

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: Прошу помощи. Тензодатчик + шаговый двигатель

вам нужно поковыряться в библиотеке тензодатчика, тормоза там

Неактивний

#3 2017-06-09 13:27:11

gorenkov
Учасник
З Кіев
Зареєстрований: 2015-11-05
Повідомлень: 41

Re: Прошу помощи. Тензодатчик + шаговый двигатель

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

Единственное что мне удалось, scales() я запускал не в loop(), а в serialParsing(). Но тогда двигатель останавливается периодически для выполнения кода весов. Может есть другие варианты асинхронного выполнения кода?

#include <Stepper.h>
#include <HX711.h>

HX711 scale(4, 5);

String serialData;
int serialDataInt;
int stopWeight = 20;
int scaleWeight;

int steps = 100;
Stepper stepper(steps, 2, 3);

void setup() {
  stepper.setSpeed(300);
  scale.set_scale(-202.13);
  scale.tare();
  scaleWeight = scale.get_units(1); //Вес без груза, с учётом тары
  Serial.begin (115200);
  Serial.println("ready!");
}

void loop() {
scales();
}


void serialEvent(){
    while (Serial.available() > 0) {
    serialData  = Serial.readStringUntil('\n');
    serialDataInt = serialData.toInt();
//    Serial.print ("String :");
//    Serial.println (serialData);
//    Serial.print ("Int :");
//    Serial.println (serialDataInt);
    }
    serialParsing();
}

void serialParsing(){
    if (serialData == "f"){
      Serial.println("forward");
      while(stopWeight > scaleWeight){
      stepperMotor();
//      scales();
      }
    stopWeight = 20;
    }
    if (serialData == "t"){
      tareScales();
      Serial.println("scales tared");
    }
    if (serialData == "s"){
      Serial.println("stop");
    }
    if (serialData > "0" && serialData <= "9"){
      stopWeight = serialDataInt;
      Serial.print("stop weight set to: ");
      Serial.println(stopWeight);
      
    }
}

void scales(){
  scale.power_up();
  scaleWeight = scale.get_units(1);
  scale.power_down();
  Serial.print("Current weight: ");
  Serial.println(scaleWeight);
}

void tareScales(){
  scale.tare();
}

void stepperMotor(){
  Serial.println("stepper motor func");
  stepper.step(steps);
}

Неактивний

#4 2017-06-09 19:52:15

qwone
Учасник
Зареєстрований: 2016-07-25
Повідомлень: 143

Re: Прошу помощи. Тензодатчик + шаговый двигатель

gorenkov пише:

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

Скорее всего в Ардуино у ардуино-программистов отсутсвует Школа программирования. Это значит, что на Ардуино можно писать асинхроноработающие программы, но у стандартного ардуинщика отсутсвует уровень знаний. Особенность маркетинга Ардуино и ничего личного.
ПС: Это же касается и библиотек на Ардуно. Зачем напрягаться и писать хорошо, народ на Ардуне сидит "дубоватый".

Остання редакція qwone (2017-06-09 19:57:23)

Неактивний

#5 2017-06-09 21:18:31

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

qwone пише:
gorenkov пише:

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

Скорее всего в Ардуино у ардуино-программистов отсутсвует Школа программирования. Это значит, что на Ардуино можно писать асинхроноработающие программы, но у стандартного ардуинщика отсутсвует уровень знаний. Особенность маркетинга Ардуино и ничего личного.
ПС: Это же касается и библиотек на Ардуно. Зачем напрягаться и писать хорошо, народ на Ардуне сидит "дубоватый".

AVR и многозадачность  lol архитектура как раз подходящая, да количество векторов, стеков и прочего завались lol . Если считать что каждая из функций выполняется условно говоря 10 мс по таймеру (количество таймеров у нас ого го  lol ) а потом "прыгает" опять же в другую то да (если допрыгнет lol ). Вы лично много написали библиотек? Может поделитесь? Плисс ссылку на гитхаб, а то мы народ вообщем "дубоватый" sad .
P.S. "ничего личного"  big_smile .

Неактивний

#6 2017-06-09 21:37:05

qwone
Учасник
Зареєстрований: 2016-07-25
Повідомлень: 143

Re: Прошу помощи. Тензодатчик + шаговый двигатель

А зачем вам мои библиотеки, вы же блин "дубоваты". Вы или ищите аппаратные возможности . Или без "аппаратных возможностей" у вас "многозадачность" сильно "озадачивается".
ПС: А мне приходится искать свой подход. А пол-дела народу не показывают.

Неактивний

#7 2017-06-09 22:09:40

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

qwone пише:

А зачем вам мои библиотеки, вы же блин "дубоваты". Вы или ищите аппаратные возможности . Или без "аппаратных возможностей" у вас "многозадачность" сильно "озадачивается".
ПС: А мне приходится искать свой подход. А пол-дела народу не показывают.

А затем что бы по правильно оценить высоту "своего дуба" lol . А то действительно как то у меня "...без "аппаратных возможностей" у вас "многозадачность" сильно "озадачивается"  lol . Да кроме этого чего то сильно смущает компилятор и стандартные библиотеки тоже, да и препроцессор того  smile . А тут бах оказывается просто "дуб".
Короче, и по теме, если каждую лепешку го@на называть пулей тогда зачем патронные заводы. Если Вам влом показать, то нефиг "звенеть кольчугой" . Извините может грубо, но не взыщите, ведь "дубоватый".

Неактивний

#8 2017-06-09 22:16:25

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: Прошу помощи. Тензодатчик + шаговый двигатель

я и не знал что есть целое направление ардуино - программистов)))
всегда был уверен что есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами.

а дуня есть ГЕНИАЛЬНОЕ И ПОЛЕЗНОЕ изобретение, позволившее миллионам людей по всему миру, не будучи программистами, что то сделать своими руками.
большинство из них, кстати, и не собираются углубляться в дебри программирования и ругать их не зачем)))

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

Неактивний

#9 2017-06-09 22:19:04

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: Прошу помощи. Тензодатчик + шаговый двигатель

а большинство выложенных в свободный доступ библиотек народ писал под свои нужды и ругать их не нужно - кого не устраивает пусть напишет под себя)))

Неактивний

#10 2017-06-09 22:53:44

gorenkov
Учасник
З Кіев
Зареєстрований: 2015-11-05
Повідомлень: 41

Re: Прошу помощи. Тензодатчик + шаговый двигатель

Вот развели холивар. А теперь к делу. В общем, немного подумав, поэкспериментировав я пришёл к такому коду:

#include <Stepper.h>
#include <HX711.h>

HX711 scale(4, 5);

String serialData;
int serialDataInt;
int stopWeight = 20;
int scaleWeight;

int steps = 100;
Stepper stepper(steps, 2, 3);

void setup() {
  scale.set_scale(-202.13);
  scale.tare();
  scaleWeight = scale.get_units(1); //Вес без груза, с учётом тары
  Serial.begin (115200);
  Serial.println("ready!");
}

void loop() {
//scales();
}


void serialEvent(){
    while (Serial.available() > 0) {
    serialData  = Serial.readStringUntil('\n');
    serialDataInt = serialData.toInt();
    Serial.print ("String :");
    Serial.println (serialData);
    Serial.print ("Int :");
    Serial.println (serialDataInt);
    }
    serialParsing();
}

void serialParsing(){
    if (serialData == "f"){
      Serial.println("forward");
      while(stopWeight > scaleWeight){
      steps = 1;  
      stepperMotor();
      scales();
      }
    scaleWeight = 0;
    stopWeight = 20;
    }
    if (serialData == "t"){
      tareScales();
      Serial.println("scales tared");
    }
    if (serialData == "s"){
      Serial.println("stop");
    }
    if (serialData == "b"){
      Serial.println("backward");
      stepper.setSpeed(100);
      stepper.step(100);
    }
    if (serialData > "0" && serialData <= "9"){
      stopWeight = serialDataInt;
      Serial.print("stop weight set to: ");
      Serial.println(stopWeight);
      
    }
}

void scales(){
  scale.power_up();
  scaleWeight = scale.get_units(1);
//  scale.power_down();
  Serial.print("Current weight: ");
  Serial.println(scaleWeight);
}

void tareScales(){
  scale.tare();
}

void stepperMotor(){
  Serial.println("stepper motor func");
  stepper.setSpeed(300);
  stepper.step(-100);
}

Это промежуточная, но полностью рабочая версия без тормозов. Может кому-то пригодится.

Неактивний

#11 2017-06-09 23:10:53

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

vvr, да вопрос в другом. Тут "новоиспеченный Цукерберг" уже на такой оказывается высоте и имеет такую "школу" а медалей вообще не сосчитать, я и попросил горсточку "самых дешевых" smile . Ну согласитесь то что он написал бестактно или по крайней мере не красиво, считать себя здесь на форуме ( хотя он замахнулся на всех ардуинщиков, а я думаю что среди них есть ну очень много которые утрут ему нос) самым "правильным" и классным прогером. И речь не о мне поскольку я не проф. программист как и не электронщик (хотя увлекся радио благодаря брату где то лет с 10), АВР увлекся где то в начале двухтысячных (еще писал на ASM). По крайней мере никогда не считал себя "дубоватым", сделал десятки устройств на атмегах. И действительно ардуино "упростило жизнь". Здесь на форуме уже была тема о "многозадачности" (может и qwone ее подымал, не помню ). Вот зачем выдавать "желаемое за действительное"? Для пиара? Ни о какой действительно многозадачности речь идти не может а только о суррогате.  Пользы от него ноль. Проще и правильно поставить два камня и не лепить горбатого. Ведь кроме перечисленных мною аппаратных ограничений есть еще одно банальное - это нужно написать действительно многозадачную ось которая сожрет уйму ресурсов и напрочь уберет все так званые "преимущества".
ТС, извините.

Остання редакція Nefreemen (2017-06-09 23:12:07)

Неактивний

#12 2017-06-10 00:49:35

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

Вячеслав, асинхронно выполняется по сути любая программа которая имеет несколько функций кроме main (loop), поэтому говорить о каких то потоках трех или n бессмысленно, все равно они выполняются последовательно по времени а не параллельно, что подразумевает многозадачность. Если подразумевать что само устройство выполняет три не зависимые функции то я бы назвал такое 3 в 1 но не многозадачностью. У меня есть тоже не одно такое устройство smile . Возьмем к примеру термостат заложим в него допустим дневную и ночную температуру. Он по сути будет контролировать два процесса время и температуру это многозадачность? Ведь программа по сути по времени будет линейна проверил температуру проверил время если надо включил нагрев или изменил температурные пределы. Только ось может дробить процесс  выполнения функций (когда процессор выполняет скажем несколько машинных команд одной функции а потом другой и возвращается обратно) а для этого понятно нужны аппаратные возможности таймеры стеки и пр. И по моему убеждению без ASM здесь не обойтись. В работе нескольких камней в одной системе как раз ничего сложного. У меня есть два устройства Pro mini + Atmega2560 + ESP8266. Работает как я хотел (мне нужна была надежность, по сути дублирование (параллель). Но это тема другой темы smile .

Неактивний

#13 2017-06-10 05:53:17

qwone
Учасник
Зареєстрований: 2016-07-25
Повідомлень: 143

Re: Прошу помощи. Тензодатчик + шаговый двигатель

vvr пише:

я и не знал что есть целое направление ардуино - программистов)))
всегда был уверен что есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами.

Я не знал что у меня, есть огромная семья... 
Да , есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами, а есть огромное "стадо" программистов пишущих в среде Ардуино на обрезаном Си. Не программно, не аппаратно обрезаном,а на морально-мол так никто не пишет. И навык написания они берут от образцов демонстрашек Ардуина и Адафрут библиотек. Которые замечательно работают, когда залиты индивидуально а МК. Вот для реализации "паралельной" работы демонстрашек и нужны (а) дублирующий камень (б) расширенные аппаратные возможности МК  поддерживающие "многозадачность". А то что парралельную работу некритичных к скорости работы устройств можно организовать и на одном МК, считают за ересь.   
  ПС: По теме. ТС , вы слышали про millis() и как с помощью него распределять работу асинхронно работающих частей программы или все так же будете топтаться на месте.

Остання редакція qwone (2017-06-10 05:53:47)

Неактивний

#14 2017-06-10 07:20:16

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: Прошу помощи. Тензодатчик + шаговый двигатель

именно для этого огромного стада и сделана дуня с её вирингом и библиотеками, которые на 100% подходят для решения огромного количества различных задач и не требуют глубокого изучения программирования.
большинству вообще достаточно Джереми Блюма и ничего в этом страшного и плохого нет.

кому нужно - идут дальше, читают другие книги, учатся.

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

Неактивний

#15 2017-06-10 07:59:07

qwone
Учасник
Зареєстрований: 2016-07-25
Повідомлень: 143

Re: Прошу помощи. Тензодатчик + шаговый двигатель

vvr пише:

именно для этого огромного стада и сделана дуня с её вирингом и библиотеками, которые на 100% подходят для решения огромного количества различных задач и не требуют глубокого изучения программирования.
большинству вообще достаточно Джереми Блюма и ничего в этом страшного и плохого нет.

кому нужно - идут дальше, читают другие книги, учатся.

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

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

Неактивний

#16 2017-06-10 12:08:43

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

qwone пише:
vvr пише:

я и не знал что есть целое направление ардуино - программистов)))
всегда был уверен что есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами.

Я не знал что у меня, есть огромная семья... 
Да , есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами, а есть огромное "стадо" программистов пишущих в среде Ардуино на обрезаном Си. Не программно, не аппаратно обрезаном,а на морально-мол так никто не пишет. И навык написания они берут от образцов демонстрашек Ардуина и Адафрут библиотек. Которые замечательно работают, когда залиты индивидуально а МК. Вот для реализации "паралельной" работы демонстрашек и нужны (а) дублирующий камень (б) расширенные аппаратные возможности МК  поддерживающие "многозадачность". А то что парралельную работу некритичных к скорости работы устройств можно организовать и на одном МК, считают за ересь.   
  ПС: По теме. ТС , вы слышали про millis() и как с помощью него распределять работу асинхронно работающих частей программы или все так же будете топтаться на месте.

Вах, вах...Огромное "стадо" (ну не могут некоторые без пьедестала ) ну никогда не слышали о millis и о структурах тем более а о форматном выводе или как сделать свое, не стандартное, преобразование типов вообще умолчу и т.д. Ну не умеем мы строить интервалы на основе millis включать один светодиод через другой интервал другой и т.д. Ну тут приходит  Америго Веспуччи и говорит да это ж многозадачность и параллельное выполнение, потом о  какой то асинхронности дылдонит. Дык сначала надо определится это асинхронность или параллельная работа? Если асинхронность то это уже априори не параллельность. А самое главное называет это многозадачность lol . Просветите "свиточ" наш ясный  "стадо", Вы выполнение команд делите буквально на машинные циклы и используете jamp (к стати а аналог в с++ есть smile ?). Вы делаете распределение программам памяти, работаете со стеками и регистрами? Или Вы все таки делаете модули и отводите им время выполнения?

Неактивний

#17 2017-06-10 17:39:44

qwone
Учасник
Зареєстрований: 2016-07-25
Повідомлень: 143

Re: Прошу помощи. Тензодатчик + шаговый двигатель

А хрен вас "Колумбов" поймешь. Или вы Сусанины , Моисеи доморощеные . Может у вас сам процесс заблудиться в Лесу "Три Сосны" прет. Вы хотели посмотреть мой код - Ловите. А как вы это назовете мне глубоко начхать.

/*.ino
  реле на вентилятор 1 -->2 (Fan1_pin)
  реле на вентилятор 2 -->3 (Fan2_pin)
  lcd1602_I2C
  таймер обратного счета
  светодиод 1          -->8  (Led1_pin)
  светодиод 2          -->9  (Led2_pin)
  светодиод 3          -->10 (Led3_pin)
  светодиод 4          -->A0 (Led4_pin)
  светодиод 5          -->A1 (Led5_pin)
  светодиод 6          -->A2 (Led6_pin)
  светодиод 7          -->13 (Led7_pin)
  кнопка 1             -->4 (btn1_pin)  кнопка смена режима /режим 10мин,20минут 40минут
  кнопка 2             -->5 (btn2_pin)  кнопка смена режима / режим 1,режим2,режим3
  кнопка 3             -->6 (btn3_pin)  кнопка старт
  кнопка 4             -->7 (btn4_pin)  кнопка стоп
  Принцип кода: Кнопкой btn1 меняется режим 10мин,20минут 40минут
                Кнопкой btn2 меняется режим вид работы
                Кнопкой btn3 меняется запуск
                Кнопкой btn4 меняется стоп
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//------------------------ Cl_back_timer ----------------------------------
// класс  таймер
class Cl_back_timer {
    uint32_t mill;
    bool stat;// 0 стоит /1 обратный счет
    void (* Do1)(), (* Do2)();
    uint32_t time ;
    void convert_time() {
      minute = time / 60000;
      sec = time / 1000 - minute * 60;
    }
    const uint32_t interval = 1000;// цикл обновления показаний
    uint32_t past = 0;
    uint32_t past_end;
  public:
    // указатель на следующий элемент
    Cl_back_timer *pnt;
    // конструктор
    Cl_back_timer(Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      mill = millis();
      if (stat && mill - past >= interval) {
        past = mill;
        if (time > interval) {
          time -= interval;
          convert_time();
          Do1();
        } else {
          stat = 0;
          Do2();
        }
      }
    }
    void Start() {
      stat = 1;
      past = millis();
      time = time_start;
    }
    void Stop() {
      stat = 0;
    }
    byte sec;
    byte minute;
    uint32_t time_start = 10000;
};
// ------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 1 обработчиком
class Cl_do_btn {
    byte pin ; // нога
    bool inv; // инверсия
    void (*Do)();
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_do_btn *pnt;
    // конструктор
    Cl_do_btn(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без внут подтяжки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin) ; // прочитать реальное значение на выводе
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_btn && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce_btn = 1;                                 // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_btn = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do()  ;
      }
    }
};
//------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 3 выборами
#include <EEPROM.h>
class Cl_do_btn_3mode {
    int adrEEPROM;
    byte pin ;// нога
    bool inv; // инверсия
    void (*Do1)(), (*Do2)() , ( *Do3)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
    byte mode;// 0,1,2 режим
  public:
    // указатель на следующий элемент
    Cl_do_btn_3mode *pnt;
    // конструктор
    Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без подтязки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      bounce = 0 ;
      btn_old = 1 ;
      btn = digitalRead(pin)^inv ; // прочитать реальное значение на выводе
      byte _mode = EEPROM.read(adrEEPROM);
      if (_mode == 0 || _mode == 1 || _mode == 2  )mode = _mode;
      else mode = 0;
      EEPROM.update(adrEEPROM, mode);
      if (mode == 0) Do1();
      else if (mode == 1) Do2();
      else Do3();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce && btn != (digitalRead(pin)^  inv)) { // если прошел фронт изм на выводн
        bounce = 1;                                      // выставить флаг
        past = millis();                                 // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin)^  inv ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) {
          (mode >= 2) ? mode = 0 : mode++;
          if (mode == 0) Do1();
          if (mode == 1) Do2();
          if (mode == 2) Do3();
        }
      }
    }
    // поставить в нужный режим
    void Set_mode(int _mode) {
      switch (_mode) {
        case 0:
          mode = 0;
          Do1();
          break;
        case 1:
          mode = 1;
          Do2();
          break;
        case 2:
          mode = 2;
          Do3();
          break;
      }
    }
};
//------------------------ Cl_fan ----------------------------------
// класс  вентилятор
class Cl_fan {
    uint32_t time_work_old; //время работы 10 минут
    uint32_t time_pulse_old; //время полного импульса 1 минута
    uint32_t time_pulse_ON_old; //время работы в течении импульса 0,5 нинут
    byte pin; // нога
    bool inv; // инверсия
    bool stat;
    bool work;
    uint32_t past_pulse;
    uint32_t past_work;
  public:
    // указатель на следующий элемент
    Cl_fan *pnt;
    // конструктор
    Cl_fan(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
      pinMode(pin, OUTPUT);
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (work && millis() - past_pulse >= time_pulse_old) {
        past_pulse = millis();
        stat = 1;
        digitalWrite(pin, stat ^ inv);
      }
      if (stat && millis() - past_pulse >= time_pulse_ON_old) {
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
      if (work && millis() - past_work >= time_work_old) {
        work = 0;
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
    }
    void ON() {
      time_work_old = time_work;
      time_pulse_old = time_pulse;
      time_pulse_ON_old = time_pulse_ON;
      past_work = millis();
      work = 1;
      past_pulse = millis();
      stat = 1;
      digitalWrite(pin, stat ^ inv);
    }
    void OFF() {
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
    }
    uint32_t time_work = 600000; //время работы 10 минут
    uint32_t time_pulse = 60000; //время полного импульса 1 минута
    uint32_t time_pulse_ON = 30000; //время работы в течении импульса 0,5 нинут
};
//------------------------ Cl_led ----------------------------------
// класс  светодиод
class Cl_led {
    byte pin ;// нога
    bool inv; // инверсия вывода
    bool led;// 0 откл / 1 вкл
    bool stat_blink;// 1 мигает/0 нет
    uint32_t past = 0;
    uint32_t time_blink = 500;
  public:
    // указатель на следующий элемент
    Cl_led *pnt;
    // конструктор
    Cl_led(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin, OUTPUT);// подключить светодиод
      OFF();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (stat_blink && millis() - past >= time_blink) {
        past = millis();
        digitalWrite(pin, led = ! led) ;
      }
    }
    // включить
    void ON() {
      stat_blink = 0;
      digitalWrite(pin, led = 1 ^ inv) ; // зажечь
    }
    // выключить
    void OFF() {
      stat_blink = 0;
      digitalWrite(pin, led = 0 ^ inv) ; // погасить
    }
    // начать мигать
    void blink() {
      stat_blink = 1;
      past = millis();
    }
    // начать мигать с опред полупериодом
    void blink(uint32_t time) {
      time_blink = time;
      stat_blink = 1;
      past = millis();
    }
};
//-----------------class Cl_sys---------------------------
class Cl_Sys {
  public:
    Cl_back_timer    *Start_back_timer   = NULL;
    Cl_do_btn        *Start_do_btn       = NULL;
    Cl_do_btn_3mode  *Start_do_btn_3mode = NULL;
    Cl_fan           *Start_fan          = NULL;
    Cl_led           *Start_led          = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      Start_back_timer  ->setup();
      Start_do_btn      ->setup();
      Start_do_btn_3mode->setup();
      Start_fan         ->setup();
      Start_led         ->setup();
    }
    // loop()
    void loop() {
      Start_back_timer  ->loop();
      Start_do_btn      ->loop();
      Start_do_btn_3mode->loop();
      Start_fan         ->loop();
      Start_led         ->loop();
    }
} Sys;
//---------описание классов------------
Cl_back_timer  ::Cl_back_timer  (Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()): Do1(_Do1), Do2(_Do2), pnt(NULL) {}
Cl_do_btn      ::Cl_do_btn      (Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)()): pin(_pin), inv(_inv), Do(_Do), pnt(NULL) {}
Cl_do_btn_3mode::Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM)
  :                                            pin(_pin), inv(_inv),    Do1(_Do1),       Do2(_Do2),       Do3(_Do3), adrEEPROM(_adrEEPROM), pnt(NULL) {}
Cl_fan         ::Cl_fan         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
Cl_led         ::Cl_led         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
//----------Компоновка---------------------
const uint32_t time_20sec =   20000; //время 20 секунд
const uint32_t time_30sec =   30000; //время 30 секунд
const uint32_t time_1min  =   60000; //время 1 минуты
const uint32_t time_3min  =  180000; //время 3 минуты
const uint32_t time_10min =  600000; //время работы 10 нинут
const uint32_t time_20min = 1200000; //время работы 20 нинут
const uint32_t time_40min = 2400000; //время работы 40 нинут
// вентилятор
Cl_fan *Fan1 = new Cl_fan(&Sys,/*пин*/2,/*инверсия*/0);// подключить реле вентилятора на выв 2, вкл если на выв 1
Cl_fan *Fan2 = new Cl_fan(&Sys,/*пин*/3,/*инверсия*/0);// подключить реле вентилятора на выв 3, вкл если на выв 1
// таймер обратного счета
void Do1_Back_timer();
void Do2_Back_timer();
Cl_back_timer *Back_timer = new Cl_back_timer(&Sys,/*обработчик*/ Do1_Back_timer, /*обработчик*/ Do2_Back_timer );
void Do1_Back_timer() {  // отправить текущие показания
  lcd.setCursor(6, 0);
  if (Back_timer->minute < 10)lcd.print("0");
  lcd.print(Back_timer->minute);
  lcd.print(":");
  if (Back_timer->sec < 10)lcd.print("0");
  lcd.print(Back_timer->sec);
}
void Do2_Back_timer() { // отправить последнее сообщение
  lcd.setCursor(6, 0);
  lcd.print(" END ");
}
// светодиоды для 1 выбора режима
Cl_led *Led1 = new Cl_led(&Sys,/*пин*/8 ,/*инверсия*/ 0);// подключить светодиод на выв 8 , горит если на выв 0
Cl_led *Led2 = new Cl_led(&Sys,/*пин*/9 ,/*инверсия*/ 0);// подключить светодиод на выв 9 , горит если на выв 0
Cl_led *Led3 = new Cl_led(&Sys,/*пин*/10,/*инверсия*/0);// подключить светодиод на выв 10, горит если на выв 0
// светодиоды для 2 выбора режима
Cl_led *Led4 = new Cl_led(&Sys,/*пин*/A0,/*инверсия*/0);// подключить светодиод на выв A0, горит если на выв 0
Cl_led *Led5 = new Cl_led(&Sys,/*пин*/A1,/*инверсия*/0);// подключить светодиод на выв A1, горит если на выв 0
Cl_led *Led6 = new Cl_led(&Sys,/*пин*/A2,/*инверсия*/0);// подключить светодиод на выв A2, горит если на выв 0
// индикатор работа
Cl_led *Led7 = new Cl_led(&Sys,/*пин*/13,/*инверсия*/0);// подключить светодиод на выв 13, горит если на выв 0
// кнопка 1
void Do1_Btn1() {
  Fan1->time_work = time_10min;
  Fan2->time_work = time_10min;
  Back_timer->time_start = time_10min;
  Led3->OFF();
  Led1->ON();
  lcd.setCursor(0, 0);
  lcd.print("10min");
}
void Do2_Btn1() {
  Fan1->time_work = time_20min;
  Fan2->time_work = time_20min;
  Back_timer->time_start = time_20min;
  Led1->OFF();
  Led2->ON();
  lcd.setCursor(0, 0);
  lcd.print("20min");
}
void Do3_Btn1() {
  Fan1->time_work = time_40min;
  Fan2->time_work = time_40min;
  Back_timer->time_start = time_40min;
  Led2->OFF();
  Led3->ON();
  lcd.setCursor(0, 0);
  lcd.print("40min");
}
Cl_do_btn_3mode *Btn1 = new Cl_do_btn_3mode(&Sys,/*пин*/4,/*инверсия*/ 0,/*обработчик*/ Do1_Btn1, /*обработчик*/ Do2_Btn1, /*обработчик*/ Do3_Btn1,/*adrEEPROM*/0x00);
//Кнопка 2
void Do1_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_1min;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led6->OFF();
  Led4->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=ON    2=1m/30");
}
void Do2_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_30sec;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led4->OFF();
  Led5->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/30 2=1m/30");
}
void Do3_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_20sec;
  Fan2->time_pulse = time_3min;
  Fan2->time_pulse_ON = time_30sec;
  Led5->OFF();
  Led6->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/20 2=3m/30");
}
Cl_do_btn_3mode *Btn2 = new Cl_do_btn_3mode(&Sys,/*пин*/5,/*инверсия*/ 0,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*обработчик*/ Do3_Btn2,/*adrEEPROM*/0x01);
//Кнопка 3 Пуск
void Do_Btn3() {
  Fan1->ON();
  Fan2->ON();
  Back_timer->Start();
  Led7->blink();
  lcd.setCursor(13, 0);
  lcd.print("ON ");
}
Cl_do_btn *Btn3 = new Cl_do_btn(&Sys,/*пин*/6,/*инверсия*/0,/*обработчик*/ Do_Btn3);
//Кнопка 4 Стоп
void Do_Btn4() {
  Fan1->OFF();
  Fan2->OFF();
  Back_timer->Stop();
  Led7->ON();
  lcd.setCursor(13, 0);
  lcd.print("OFF ");
}
Cl_do_btn *Btn4 = new Cl_do_btn(&Sys,/*пин*/7,/*инверсия*/ 0,/*обработчик*/Do_Btn4);
//-----------Main()-----------------------
void setup() {
  lcd.init();
  lcd.backlight();
  Sys.setup();
}
void loop() {
  Sys.loop();
}

Неактивний

#18 2017-06-10 19:06:06

vvr
Учасник
Зареєстрований: 2015-04-12
Повідомлень: 874

Re: Прошу помощи. Тензодатчик + шаговый двигатель

qwone пише:

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

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

Неактивний

#19 2017-06-10 21:10:35

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Прошу помощи. Тензодатчик + шаговый двигатель

qwone пише:

А хрен вас "Колумбов" поймешь. Или вы Сусанины , Моисеи доморощеные . Может у вас сам процесс заблудиться в Лесу "Три Сосны" прет. Вы хотели посмотреть мой код - Ловите. А как вы это назовете мне глубоко начхать.

/*.ino
  реле на вентилятор 1 -->2 (Fan1_pin)
  реле на вентилятор 2 -->3 (Fan2_pin)
  lcd1602_I2C
  таймер обратного счета
  светодиод 1          -->8  (Led1_pin)
  светодиод 2          -->9  (Led2_pin)
  светодиод 3          -->10 (Led3_pin)
  светодиод 4          -->A0 (Led4_pin)
  светодиод 5          -->A1 (Led5_pin)
  светодиод 6          -->A2 (Led6_pin)
  светодиод 7          -->13 (Led7_pin)
  кнопка 1             -->4 (btn1_pin)  кнопка смена режима /режим 10мин,20минут 40минут
  кнопка 2             -->5 (btn2_pin)  кнопка смена режима / режим 1,режим2,режим3
  кнопка 3             -->6 (btn3_pin)  кнопка старт
  кнопка 4             -->7 (btn4_pin)  кнопка стоп
  Принцип кода: Кнопкой btn1 меняется режим 10мин,20минут 40минут
                Кнопкой btn2 меняется режим вид работы
                Кнопкой btn3 меняется запуск
                Кнопкой btn4 меняется стоп
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//------------------------ Cl_back_timer ----------------------------------
// класс  таймер
class Cl_back_timer {
    uint32_t mill;
    bool stat;// 0 стоит /1 обратный счет
    void (* Do1)(), (* Do2)();
    uint32_t time ;
    void convert_time() {
      minute = time / 60000;
      sec = time / 1000 - minute * 60;
    }
    const uint32_t interval = 1000;// цикл обновления показаний
    uint32_t past = 0;
    uint32_t past_end;
  public:
    // указатель на следующий элемент
    Cl_back_timer *pnt;
    // конструктор
    Cl_back_timer(Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      mill = millis();
      if (stat && mill - past >= interval) {
        past = mill;
        if (time > interval) {
          time -= interval;
          convert_time();
          Do1();
        } else {
          stat = 0;
          Do2();
        }
      }
    }
    void Start() {
      stat = 1;
      past = millis();
      time = time_start;
    }
    void Stop() {
      stat = 0;
    }
    byte sec;
    byte minute;
    uint32_t time_start = 10000;
};
// ------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 1 обработчиком
class Cl_do_btn {
    byte pin ; // нога
    bool inv; // инверсия
    void (*Do)();
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_do_btn *pnt;
    // конструктор
    Cl_do_btn(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без внут подтяжки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin) ; // прочитать реальное значение на выводе
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_btn && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce_btn = 1;                                 // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_btn = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do()  ;
      }
    }
};
//------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 3 выборами
#include <EEPROM.h>
class Cl_do_btn_3mode {
    int adrEEPROM;
    byte pin ;// нога
    bool inv; // инверсия
    void (*Do1)(), (*Do2)() , ( *Do3)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
    byte mode;// 0,1,2 режим
  public:
    // указатель на следующий элемент
    Cl_do_btn_3mode *pnt;
    // конструктор
    Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без подтязки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      bounce = 0 ;
      btn_old = 1 ;
      btn = digitalRead(pin)^inv ; // прочитать реальное значение на выводе
      byte _mode = EEPROM.read(adrEEPROM);
      if (_mode == 0 || _mode == 1 || _mode == 2  )mode = _mode;
      else mode = 0;
      EEPROM.update(adrEEPROM, mode);
      if (mode == 0) Do1();
      else if (mode == 1) Do2();
      else Do3();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce && btn != (digitalRead(pin)^  inv)) { // если прошел фронт изм на выводн
        bounce = 1;                                      // выставить флаг
        past = millis();                                 // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin)^  inv ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) {
          (mode >= 2) ? mode = 0 : mode++;
          if (mode == 0) Do1();
          if (mode == 1) Do2();
          if (mode == 2) Do3();
        }
      }
    }
    // поставить в нужный режим
    void Set_mode(int _mode) {
      switch (_mode) {
        case 0:
          mode = 0;
          Do1();
          break;
        case 1:
          mode = 1;
          Do2();
          break;
        case 2:
          mode = 2;
          Do3();
          break;
      }
    }
};
//------------------------ Cl_fan ----------------------------------
// класс  вентилятор
class Cl_fan {
    uint32_t time_work_old; //время работы 10 минут
    uint32_t time_pulse_old; //время полного импульса 1 минута
    uint32_t time_pulse_ON_old; //время работы в течении импульса 0,5 нинут
    byte pin; // нога
    bool inv; // инверсия
    bool stat;
    bool work;
    uint32_t past_pulse;
    uint32_t past_work;
  public:
    // указатель на следующий элемент
    Cl_fan *pnt;
    // конструктор
    Cl_fan(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
      pinMode(pin, OUTPUT);
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (work && millis() - past_pulse >= time_pulse_old) {
        past_pulse = millis();
        stat = 1;
        digitalWrite(pin, stat ^ inv);
      }
      if (stat && millis() - past_pulse >= time_pulse_ON_old) {
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
      if (work && millis() - past_work >= time_work_old) {
        work = 0;
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
    }
    void ON() {
      time_work_old = time_work;
      time_pulse_old = time_pulse;
      time_pulse_ON_old = time_pulse_ON;
      past_work = millis();
      work = 1;
      past_pulse = millis();
      stat = 1;
      digitalWrite(pin, stat ^ inv);
    }
    void OFF() {
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
    }
    uint32_t time_work = 600000; //время работы 10 минут
    uint32_t time_pulse = 60000; //время полного импульса 1 минута
    uint32_t time_pulse_ON = 30000; //время работы в течении импульса 0,5 нинут
};
//------------------------ Cl_led ----------------------------------
// класс  светодиод
class Cl_led {
    byte pin ;// нога
    bool inv; // инверсия вывода
    bool led;// 0 откл / 1 вкл
    bool stat_blink;// 1 мигает/0 нет
    uint32_t past = 0;
    uint32_t time_blink = 500;
  public:
    // указатель на следующий элемент
    Cl_led *pnt;
    // конструктор
    Cl_led(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin, OUTPUT);// подключить светодиод
      OFF();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (stat_blink && millis() - past >= time_blink) {
        past = millis();
        digitalWrite(pin, led = ! led) ;
      }
    }
    // включить
    void ON() {
      stat_blink = 0;
      digitalWrite(pin, led = 1 ^ inv) ; // зажечь
    }
    // выключить
    void OFF() {
      stat_blink = 0;
      digitalWrite(pin, led = 0 ^ inv) ; // погасить
    }
    // начать мигать
    void blink() {
      stat_blink = 1;
      past = millis();
    }
    // начать мигать с опред полупериодом
    void blink(uint32_t time) {
      time_blink = time;
      stat_blink = 1;
      past = millis();
    }
};
//-----------------class Cl_sys---------------------------
class Cl_Sys {
  public:
    Cl_back_timer    *Start_back_timer   = NULL;
    Cl_do_btn        *Start_do_btn       = NULL;
    Cl_do_btn_3mode  *Start_do_btn_3mode = NULL;
    Cl_fan           *Start_fan          = NULL;
    Cl_led           *Start_led          = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      Start_back_timer  ->setup();
      Start_do_btn      ->setup();
      Start_do_btn_3mode->setup();
      Start_fan         ->setup();
      Start_led         ->setup();
    }
    // loop()
    void loop() {
      Start_back_timer  ->loop();
      Start_do_btn      ->loop();
      Start_do_btn_3mode->loop();
      Start_fan         ->loop();
      Start_led         ->loop();
    }
} Sys;
//---------описание классов------------
Cl_back_timer  ::Cl_back_timer  (Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()): Do1(_Do1), Do2(_Do2), pnt(NULL) {}
Cl_do_btn      ::Cl_do_btn      (Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)()): pin(_pin), inv(_inv), Do(_Do), pnt(NULL) {}
Cl_do_btn_3mode::Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM)
  :                                            pin(_pin), inv(_inv),    Do1(_Do1),       Do2(_Do2),       Do3(_Do3), adrEEPROM(_adrEEPROM), pnt(NULL) {}
Cl_fan         ::Cl_fan         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
Cl_led         ::Cl_led         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
//----------Компоновка---------------------
const uint32_t time_20sec =   20000; //время 20 секунд
const uint32_t time_30sec =   30000; //время 30 секунд
const uint32_t time_1min  =   60000; //время 1 минуты
const uint32_t time_3min  =  180000; //время 3 минуты
const uint32_t time_10min =  600000; //время работы 10 нинут
const uint32_t time_20min = 1200000; //время работы 20 нинут
const uint32_t time_40min = 2400000; //время работы 40 нинут
// вентилятор
Cl_fan *Fan1 = new Cl_fan(&Sys,/*пин*/2,/*инверсия*/0);// подключить реле вентилятора на выв 2, вкл если на выв 1
Cl_fan *Fan2 = new Cl_fan(&Sys,/*пин*/3,/*инверсия*/0);// подключить реле вентилятора на выв 3, вкл если на выв 1
// таймер обратного счета
void Do1_Back_timer();
void Do2_Back_timer();
Cl_back_timer *Back_timer = new Cl_back_timer(&Sys,/*обработчик*/ Do1_Back_timer, /*обработчик*/ Do2_Back_timer );
void Do1_Back_timer() {  // отправить текущие показания
  lcd.setCursor(6, 0);
  if (Back_timer->minute < 10)lcd.print("0");
  lcd.print(Back_timer->minute);
  lcd.print(":");
  if (Back_timer->sec < 10)lcd.print("0");
  lcd.print(Back_timer->sec);
}
void Do2_Back_timer() { // отправить последнее сообщение
  lcd.setCursor(6, 0);
  lcd.print(" END ");
}
// светодиоды для 1 выбора режима
Cl_led *Led1 = new Cl_led(&Sys,/*пин*/8 ,/*инверсия*/ 0);// подключить светодиод на выв 8 , горит если на выв 0
Cl_led *Led2 = new Cl_led(&Sys,/*пин*/9 ,/*инверсия*/ 0);// подключить светодиод на выв 9 , горит если на выв 0
Cl_led *Led3 = new Cl_led(&Sys,/*пин*/10,/*инверсия*/0);// подключить светодиод на выв 10, горит если на выв 0
// светодиоды для 2 выбора режима
Cl_led *Led4 = new Cl_led(&Sys,/*пин*/A0,/*инверсия*/0);// подключить светодиод на выв A0, горит если на выв 0
Cl_led *Led5 = new Cl_led(&Sys,/*пин*/A1,/*инверсия*/0);// подключить светодиод на выв A1, горит если на выв 0
Cl_led *Led6 = new Cl_led(&Sys,/*пин*/A2,/*инверсия*/0);// подключить светодиод на выв A2, горит если на выв 0
// индикатор работа
Cl_led *Led7 = new Cl_led(&Sys,/*пин*/13,/*инверсия*/0);// подключить светодиод на выв 13, горит если на выв 0
// кнопка 1
void Do1_Btn1() {
  Fan1->time_work = time_10min;
  Fan2->time_work = time_10min;
  Back_timer->time_start = time_10min;
  Led3->OFF();
  Led1->ON();
  lcd.setCursor(0, 0);
  lcd.print("10min");
}
void Do2_Btn1() {
  Fan1->time_work = time_20min;
  Fan2->time_work = time_20min;
  Back_timer->time_start = time_20min;
  Led1->OFF();
  Led2->ON();
  lcd.setCursor(0, 0);
  lcd.print("20min");
}
void Do3_Btn1() {
  Fan1->time_work = time_40min;
  Fan2->time_work = time_40min;
  Back_timer->time_start = time_40min;
  Led2->OFF();
  Led3->ON();
  lcd.setCursor(0, 0);
  lcd.print("40min");
}
Cl_do_btn_3mode *Btn1 = new Cl_do_btn_3mode(&Sys,/*пин*/4,/*инверсия*/ 0,/*обработчик*/ Do1_Btn1, /*обработчик*/ Do2_Btn1, /*обработчик*/ Do3_Btn1,/*adrEEPROM*/0x00);
//Кнопка 2
void Do1_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_1min;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led6->OFF();
  Led4->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=ON    2=1m/30");
}
void Do2_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_30sec;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led4->OFF();
  Led5->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/30 2=1m/30");
}
void Do3_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_20sec;
  Fan2->time_pulse = time_3min;
  Fan2->time_pulse_ON = time_30sec;
  Led5->OFF();
  Led6->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/20 2=3m/30");
}
Cl_do_btn_3mode *Btn2 = new Cl_do_btn_3mode(&Sys,/*пин*/5,/*инверсия*/ 0,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*обработчик*/ Do3_Btn2,/*adrEEPROM*/0x01);
//Кнопка 3 Пуск
void Do_Btn3() {
  Fan1->ON();
  Fan2->ON();
  Back_timer->Start();
  Led7->blink();
  lcd.setCursor(13, 0);
  lcd.print("ON ");
}
Cl_do_btn *Btn3 = new Cl_do_btn(&Sys,/*пин*/6,/*инверсия*/0,/*обработчик*/ Do_Btn3);
//Кнопка 4 Стоп
void Do_Btn4() {
  Fan1->OFF();
  Fan2->OFF();
  Back_timer->Stop();
  Led7->ON();
  lcd.setCursor(13, 0);
  lcd.print("OFF ");
}
Cl_do_btn *Btn4 = new Cl_do_btn(&Sys,/*пин*/7,/*инверсия*/ 0,/*обработчик*/Do_Btn4);
//-----------Main()-----------------------
void setup() {
  lcd.init();
  lcd.backlight();
  Sys.setup();
}
void loop() {
  Sys.loop();
}

Точно "поперло", ржу не могу  lol , утрите мне слезы...Классика жанра как нужно делать подмену понятий. Действительно, учебник как продать три сосны как лес lol . Кто в теме тот поймет и без моих комментариев smile .

Неактивний

#20 2017-06-11 11:39:02

Green
Учасник
Зареєстрований: 2015-11-08
Повідомлень: 593

Re: Прошу помощи. Тензодатчик + шаговый двигатель

Чем не обфускация? При открытых то исходниках. А по простому и дурак сможет! А так, лох цепенеет, стадо нервно курит в сторонке... И сразу тебе уважение, и бабосы рекой.)))

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму