Помогите новичку. очень простой проект, мучаюсь 3 дня.

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Помогите со скетчем новичку. Для учебы надо сделать скетч под симуляцию примитивного конвеера со счетчиком. Уже 3 дня мучаюсь, на одном месте. 

Есть конвеер, едет, пока счетчик не насчитает определенное количество допустим кубиков, 5 или 10 (2 режима счетчика) затем мотор отключается, конвеер перекрывается шторкой и с него снимаются отсчитанные ранее предметы. Порты ввода вывода сконфигурировал а вот с циклами беда. Куда какой пихать, с областями видимости переменных тоже беда. Может кто поможет идеей. Сделать через FOR, Switch, While или как то иначе.

Всем не равнодушним заранее благодарность.


/*Digital Inupt's*/
	#define SW_Start 2
	#define SW_Stop 3
	#define SW_5 4
	#define SW_10 5
	#define Counter 6
/*Digital Outputs*/
	#define Motor 7
	#define Lock 8
	#define Pull 9

void setup() {

  pinMode(SW_Start, INPUT);
  pinMode(SW_Stop, INPUT);
  pinMode(SW_5, INPUT);
  pinMode(SW_10, INPUT);
  pinMode(Counter, INPUT);
  pinMode(Motor, OUTPUT);
  pinMode(Lock, OUTPUT);
  pinMode(Pull, OUTPUT); 
  Serial.begin(9600); 
  
}	

/*VARIABLES*/
	bool start_flag, stop_flag, work_flag, count_5, count_10=0;
	byte count=0;

		
void loop() 
{
   
	



}

 

Logik
Онлайн
Зарегистрирован: 05.08.2014

Такой охеренный объем проделаной работы никого не оставит равнодушным ))))))))

Вали отсюдова учится!

saftik
Offline
Зарегистрирован: 08.04.2015

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

код далек от идеала
много лишнего (кнопок) много портов занято
от delay() нужно избавиться 
можно убрать кнопку sw5 сделать чтоб по умолчанию было 5 кубиков а при нажатии кнопки переключить на 10 при повторном нажатии опять 5
кнопку старт стоп можно тоже одну сделать

/*Идеология:
   нажатием на кнопки SW_5 или  SW_10 выибираете количество кубиков (сначало выбираем количество потом старт)
   кнопка старт запускает ленту
   лента остановиться если нажать кнопку стоп или если счетчик будет 0
*/
//Digital Inupt's
#define SW_Start 2
#define SW_Stop 3
#define SW_5 4
#define SW_10 5
#define Sensor 6 // сенсор
// Digital Outputs
#define Motor 7
#define Lock 8
#define Pull 9
byte flag_motor = 0;
byte couter = 0;

void setup() {

  pinMode(SW_Start, INPUT_PULLUP);
  pinMode(SW_Stop, INPUT_PULLUP);     //вкл подт-й резистор
  pinMode(SW_5, INPUT_PULLUP);
  pinMode(SW_10, INPUT_PULLUP);
  pinMode(Sensor, INPUT_PULLUP);
  pinMode(Motor, OUTPUT);
  pinMode(Lock, OUTPUT);
  pinMode(Pull, OUTPUT);
  Serial.begin(9600);

}

void loop()
{
  knopki();
  if ( couter > 0) {                     // если выбрали количество кубиков
    if (flag_motor == 1) {               // и нажали старт
      digitalWrite(Motor, HIGH);         // запустить мотор
      flag_motor = 2;                    // запомнили что мотор включен
    }

    if (flag_motor == 2 && digitalRead(Sensor) == LOW) {      // если работает мотор сработал сенсор
      couter = couter - 1 ;              // "списать" кубик
    }
  }
  if ( flag_motor == 0) {                // если нажали стоп
    digitalWrite(Motor, LOW);            // остановить мотор
  }
  if ( flag_motor == 2 && couter == 0) { // если все кубики "списаны"
    flag_motor = 0;                      // обнуляем флаг
  }
}



void knopki()
{
  if (SW_Start == LOW) {
    delay(100);     // задержка на дребезг
    flag_motor = 1;
  }

  if (SW_Stop == LOW) {
    delay(100);     // задержка на дребезг
    flag_motor = 0;
  }


  if (SW_5 == LOW) {
    delay(100);     // задержка на дребезг
    couter = 5;
  }

  if (SW_10 == LOW) {
    delay(100);     // задержка на дребезг
    couter = 10;
  }




}

 

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Спасибо за толчок в верном направлении. подправил код под ARDUINO нюансы и работает.


//Digital Inupt's
	#define SW_Start 2
	#define SW_Stop 3
	#define SW_5 4
	#define SW_10 5
	#define Sensor 6 
// Digital Outputs
	#define Motor 7
	#define Lock 8
	#define Pull 9

byte flag_motor,flag_state,i = 0;
bool lock_state=LOW;
const long interval_1s = 1000;
const long interval_500ms = 500;

byte counter = 0;

void setup() {

  pinMode(SW_Start, INPUT_PULLUP);
  pinMode(SW_Stop, INPUT_PULLUP);     
  pinMode(SW_5, INPUT_PULLUP);
  pinMode(SW_10, INPUT_PULLUP);
  pinMode(Sensor, INPUT_PULLUP);
  pinMode(Motor, OUTPUT);
  pinMode(Lock, OUTPUT);
  pinMode(Pull, OUTPUT);
  Serial.begin(9600);
  
}

void loop(){
	
  	buttons_state();

if (counter > 0) {                     						// if count mode is on
        
    if (flag_motor == 1) {               						// start was pressed
      digitalWrite(Motor, HIGH);         						// motor start
      Serial.print("Motor flag is ");  
      Serial.print(flag_motor);
      Serial.println();
      flag_motor = 2;                    						// save motor state
    }    

    if(flag_motor == 2 && digitalRead(Sensor) == LOW) {      	// motor on & sensor ON
    delay(250);
    Serial.println();
    Serial.print("count value is ");  
    Serial.print(counter);    
    counter=counter-1;     
    }

  }
  if (flag_motor == 0) {                						// if stop was pressed
    digitalWrite(Motor, LOW);           						// motor stop
  }
  if (flag_motor == 2 && counter == 0) {						// if all count done
    flag_motor = 0;
    digitalWrite(Motor, LOW);

    lock_pull();           										// motor tag is false
  	flag_motor=1;
  	delay(100);
  }}

void buttons_state(){

  if (digitalRead (SW_Start) == LOW) {
    delay(200);     // задержка на дребезг
    flag_motor = 1;   
    for(i=0; i<1; i++){

       if(counter==5){Serial.println();
       	Serial.println("counter mode is 5");}
       if(counter==10){Serial.println();
       	Serial.println("counter mode is 10");}     
       }  
  }

  if (digitalRead(SW_Stop) == LOW) {
    Serial.println();
    delay(150);     // задержка на дребезг
    flag_motor = 0; 
    counter=0;   
    for(i=0; i<1; i++){       
      Serial.println("!flag_motor");
      Serial.print("count value is ");  
      Serial.print(counter);
      Serial.println();          
       
    }}
  
    if(counter<1&&counter<=5&&digitalRead(SW_5)==LOW){ 
  	delay(100);
  	counter=0;
  	counter = 5;}

  if (counter<1&&counter<10&&digitalRead(SW_10) == LOW){
    delay(100);  
    counter=0;   
    counter = 10;}  
  }

void lock_pull(){

		Serial.println();
		Serial.println("lock_pull");
        digitalWrite(Motor, LOW);
        Serial.print("Motor flag is ");  
      	Serial.print(flag_motor);
      	Serial.println();
        delay(100);
        digitalWrite(Lock, HIGH);
        delay(1000);
        digitalWrite(Lock, LOW);
    	delay(500);

}

Еще есть вопросик как избавится от delay(); ибо пишут все что очень не хорошая штука для работы программы? Нашел примеры как это сделать, но что то не получается по человечески, как обычно с первого раза.

прикреплю файл протеуса, чтобы нагляднее.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

Такой охеренный объем проделаной работы никого не оставит равнодушным ))))))))

Вали отсюдова учится!

Ты что такой злой сегодня )))

 

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Logik пишет:

Такой охеренный объем проделаной работы никого не оставит равнодушным ))))))))

Вали отсюдова учится!

век живи, век учись.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

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

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

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

отвечаю. Согласно ТЗ опрос кнопок должен быть доступен с любого участка программы и в любой момент. А при использовании delay(); это не возможно, так как выполнение программы останавливается на время задержки.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

pdjboy пишет:

отвечаю. Согласно ТЗ опрос кнопок должен быть доступен с любого участка программы и в любой момент. А при использовании delay(); это не возможно, так как выполнение программы останавливается на время задержки.

Строго говоря, есть один способ сделать так, чтобы и овцы целы, и волки сыты, а именно: заюзать функцию позднего связывания yield. Цитирую исходник функции delay:

void delay(unsigned long ms)
{
	uint16_t start = (uint16_t)micros();

	while (ms > 0) {
		yield();
		if (((uint16_t)micros() - start) >= 1000) {
			ms--;
			start += 1000;
		}
	}
}

В строке 6 видно, что вызывается yield(). Которая - нигде не определена, т.к. в её объявлении указано, что она является функцией позднего связывания:

void yield(void) __attribute__ ((weak, alias("__empty")));

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

void yield()
{
// тут опрос кнопок
}

void loop()
{
...
}

По факту - получим и присутствие delay, и опрос кнопок. Сам юзаю yield, но для других задач, хотя и схожих по факту: когда во время работы ресурсоёмкого по части времени алгоритма надо обновлять чего-то там, типа энкодеров и т.п.

b707
Offline
Зарегистрирован: 26.05.2017

DIYMan, только надо отметить, что задачи, вызываемые в коде yield(), должны выполнятся относительно быстро и не должны сами использовать delay(), иначе ардуину легко наглухо завесить. Именно поэтому эта возможность и не попала в буквари для чайников...

Кстати, у ТС опрос кнопок довольно объемный и с делеями... - yield() ему не подойдет.

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

Но вообще это все - "костыли". Что касается кода ТС - "Тут всю систему менять надо" (с)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

b707 пишет:

DIYMan, только надо отметить, что задачи, вызываемые в коде yield(), должны выполнятся относительно быстро и не должны сами использовать delay()

Но вообще это все - "костыли". Что касается кода ТС - "Тут всю систему менять надо" (с)

В точку ;)

Logik
Онлайн
Зарегистрирован: 05.08.2014

b707 пишет:

Но вообще это все - "костыли". Что касается кода ТС - "Тут всю систему менять надо" (с)

ага. добрый saftik "помог" :)

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Если у Вас есть другие предложения то излогайте. Такое количество if-ов  всем не по душе. Хотя и так будет работать. Думал через SWITCH сделать или как то иначе можно по роскинуть мыслями.

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

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

ПС: Такие задачи программируют примитивно, по методичке, быстро и легко.

saftik
Offline
Зарегистрирован: 08.04.2015

Я не заявлял себя программистом. Ардуино это хобби. Я сам прошёл по пути когда задаеш вопросы а тебе вместо подсказок указывают куда идти. Я же осознают что ТС не проделал никакой работы но я попытался ему хотябы как то намекнуть на логику кода. Постарался объяснить на доступном языке.
Более того скажу . мы тут не делаем эталонные приборы. Не собираемся запускать линию производства. Человеку надо для учёбы.
И думаю пусть код будет на костылях но если он будет работать и стабильно. То не обязательно извращаться. . все остальное придёт с опытом.
А вы Logic как опытный программист могли бы и подсказать хотябы логику кода.
Я понимаю книжки теория. Но например мне трудно понять написанное иногда проще когда тебе обьяснят на пальцах.
Думаю и форум нужен для того чтоб советоваться а не посылать друг друга.
Простите за прямолинейность

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

saftik пишет:
Я не заявлял себя программистом...Простите за прямолинейность
Так я тоже не программист, я тоже не зарабатываю на этом денег. Но программирование дело коллективное. Если вы выкладываете скетч, то будьте готовы к шквалу критики. Да и на меня критики много. И что. Я тогда решаю, что верно, а что так стеб. 

  Простите за аналогию. Вы за рулем машины. Ведь машина ваша, и руль ваш.  И кому нах*ер нужно указывать, как на ней ехать. Что по правой стороне, что по левой, что на зеленый, что на красный. Но ведь придумали ПДД, службу ГАИ (или что там у вас). Штрафы берут с шоферов любителей. Блин и никакой свободы, и за рулем сидят совсем не профессионалы.  Вот так и с программированием.

Простите за прямолинейность.

saftik
Offline
Зарегистрирован: 08.04.2015

Я не вам писал )) h
Моё сообщение адресовано logik
Но конструктивная критика принимается

b707
Offline
Зарегистрирован: 26.05.2017

saftik пишет:
Я понимаю книжки теория. Но например мне трудно понять написанное иногда проще когда тебе обьяснят на пальцах. Думаю и форум нужен для того чтоб советоваться а не посылать друг друга. Простите за прямолинейность

Вот это интересный вопрос из области человековедения :) Все люди делятся на тех, кто получает информацию из книг, документации, даташитов - и на тех, кому обязательно нужно у кого-то спросить. К примеру, "saftik" проще, когда ему обьясняют на пальцах. А я вот "на пальцах" не воспринимаю вообще.  Категорически. Иногда другие даже обижаются - типа, если тебе что-то непонятно - спроси! , а мне все равно проще книжку почитать, даже когда рядом есть кто-то опытный. Я не представляю, как, к примеру,на пальцах обьяснить квантовую теорию или стиль программирования... да и зачем это обьяснять, коги есть учебники?

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

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

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

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

b707 пишет:

А я вот "на пальцах" не воспринимаю вообще.  Категорически...

Я не представляю, как, к примеру,на пальцах обьяснить квантовую теорию или стиль программирования... да и зачем это обьяснять, коги есть учебники?

А я вот помню, мой сын решал численными методами систему дифференциальных уравнений в частных производных второго порядка. В 8-м классе. Не имея ни малейшего представления, что такое численные методы, что такое дифференциальное уравнение, и, тем более - его порядок, и что такое частная производная.

Просто перед этим я с ним "на пальцах" разобрал физику явления.

Сейчас он к.ф.-м.н. Так что "на пальцах" совсем не помешало ему развивиаться.

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

 

arduino328
Offline
Зарегистрирован: 01.09.2016

qwone пишет:

за рулем сидят совсем не профессионалы

За рулём сидят роботы, управляемые Ардуино :)

arduino328
Offline
Зарегистрирован: 01.09.2016

pdjboy пишет:

беседы на вольные темы перенесите в другой топ

Вроде на форуме давно, но так и не понял, что вольное общение тут в почти каждой теме.

b707
Offline
Зарегистрирован: 26.05.2017

andriano пишет:

[ Так что "на пальцах" совсем не помешало ему развивиаться.

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

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

arduino328 пишет:

pdjboy пишет:

беседы на вольные темы перенесите в другой топ

Вроде на форуме давно, но так и не понял, что вольное общение тут в почти каждой теме.

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

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Спасибо всем кто помог, словом и делом.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Эта задача примитивная. Вот вам буквально на пальцах ее написание. У ТС 4 кнопки и 1 конвейеp. И что бы они работали нормально надо разместить их части в объявлении , в setup-е и в loop-е.  В общем начинается с этого.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
  public:
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//--------------------------------
// класс ковейер
class Cl_Transporter {
  protected:
  public:
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Btn Btn1;
Cl_Btn Btn2;
Cl_Btn Btn3;
Cl_Btn Btn4;
Cl_Transporter Transporter;
//---main-----------------------------
void setup() {
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();
  Transporter.init();
}

void loop() {
  mill = millis();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
  Transporter.run();
}
/*Скетч использует 482 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 13 байт (0%) динамической памяти, оставляя 2035 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Про кнопки я неоднократно говорил на этом форуме. От кнопок человеку ничего не надо. Ни состояние ни дребезг ни прочая мура. С помощью кнопок человек управляет Ардуиной. Нажали на кнопку и выполнелась обределеная функция один раз и все. 

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//--------------------------------
// класс ковейер
class Cl_Transporter {
  protected:
  public:
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
void DoStart() {
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
Cl_Transporter Transporter;
//---main-----------------------------
void setup() {
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();
  Transporter.init();
}

void loop() {
  mill = millis();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
  Transporter.run();
}
/* Скетч использует 592 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Разумеется ТС хочет управлять с помощью кнопок конвейером. Так что создадим методы класса ковейер и подключим к кнопкам. И да объявим конвейер перед кнопками, что бы не задействовать механизм предварельного объявления.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс ковейер
class Cl_Transporter {
  protected:
  public:
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Transporter Transporter;
void DoStart() {
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Transporter.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Transporter.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);

//---main-----------------------------
void setup() {
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();
  Transporter.init();
}

void loop() {
  mill = millis();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
  Transporter.run();
}
/* Скетч использует 592 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

У транспортера Мотор шторка и толкатель. Подключим их к пинам

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс ковейер
class Cl_Transporter {
  protected:
    byte motorPin, lockPin, pullPin;
  public:
    /*конструктор*/
    Cl_Transporter(byte motorPin_, byte lockPin_, byte pullPin_)
      : motorPin(motorPin_), lockPin(lockPin_), pullPin(pullPin_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
void DoStart() {
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Transporter.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Transporter.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);

//---main-----------------------------
void setup() {
  Transporter.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}

void loop() {
  mill = millis();
  Transporter.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 608 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 28 байт (1%) динамической памяти, оставляя 2020 байт для локальных переменных. Максимум: 2048 байт.
*/

 

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Круто, спасибо) Не совсем понятно правда что написать в этих функциях:

/*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
на сколько я понял нужно добавить еще опцию отсчета продукта согласно режиму счетчика.
Писать что делать с портами согласно назначения функции?
 
 /*инициализация- вставить в setup*/
    void init() {} // тут сконфигурировать порты?
    /*работа- вставить в loop*/
    void run() {} //что сюда вписать не понял

 

XManiac
Offline
Зарегистрирован: 21.04.2015

qwone 

Александр Ф Скляр сказал бы - "Так надо!" (с)

За такие "на пальцах" нестыдно и денег брать, с новичков особенно!)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

pdjboy пишет:
на сколько я понял нужно добавить еще опцию отсчета продукта согласно режиму счетчика.
Точно . Надо добавить класс Учетчик, который будет вам считать предметы.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс ковейер
class Cl_Transporter {
  protected:
    byte motorPin, lockPin, pullPin;
  public:
    /*конструктор*/
    Cl_Transporter(byte motorPin_, byte lockPin_, byte pullPin_)
      : motorPin(motorPin_), lockPin(lockPin_), pullPin(pullPin_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
  public:
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
Cl_Check Check;
void DoStart() {
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Transporter.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Transporter.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
//---main-----------------------------
void setup() {
  Transporter.init();
  Check.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}

void loop() {
  mill = millis();
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 608 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 28 байт (1%) динамической памяти, оставляя 2020 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Теперь решим что надо учетчику. Разумеется пин который считает предметы. Опять же сюда надо перевести режим подсчета на 5 и 10 предметов и наконец обработчик который командует транспортеру остановиться.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс конвейер
class Cl_Transporter {
  protected:
    byte motorPin, lockPin, pullPin;
  public:
    /*конструктор*/
    Cl_Transporter(byte motorPin_, byte lockPin_, byte pullPin_)
      : motorPin(motorPin_), lockPin(lockPin_), pullPin(pullPin_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*разгрузить конвейep*/
    void swap() {}
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Check(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
void DoCheck() {
  Transporter.swap();
}
Cl_Check Check(/*пин счетчика*/6,/*обработчик*/&DoCheck);
void DoStart() {
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Check.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Check.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
//---main-----------------------------
void setup() {
  Transporter.init();
  Check.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}
void loop() {
  mill = millis();
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 626 байт (2%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 31 байт (1%) динамической памяти, оставляя 2017 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Пользуясь этим #6   :)  Расписываем класс кнопки , а так же подключаем Serial

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс конвейер
class Cl_Transporter {
  protected:
    byte motorPin, lockPin, pullPin;
  public:
    /*конструктор*/
    Cl_Transporter(byte motorPin_, byte lockPin_, byte pullPin_)
      : motorPin(motorPin_), lockPin(lockPin_), pullPin(pullPin_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*разгрузить конвейep*/
    void swap() {}
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
  public:
    /*констрктор*/
    Cl_Check(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*режим5 предметов*/
    void mode5() {}
    /*режим10 предметов*/
    void mode10() {}
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
  public:
    /*констрктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа- вставить в loop*/
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) Do();
      }
    }
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
void DoCheck() {
  Transporter.swap();
}
Cl_Check Check(/*пин счетчика*/6,/*обработчик*/&DoCheck);
void DoStart() {
  Serial.println("Transporter Start");
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Serial.println("Transporter Stop");
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Serial.println("DoMode5");
  Check.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Serial.println("DoMode10");
  Check.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  Transporter.init();
  Check.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}
void loop() {
  mill = millis();
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 2282 байт (7%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 288 байт (14%) динамической памяти, оставляя 1760 байт для локальных переменных. Максимум: 2048 байт.
*/

 

Logik
Онлайн
Зарегистрирован: 05.08.2014

saftik пишет:
Я не заявлял себя программистом. Ардуино это хобби. Я сам прошёл по пути когда задаеш вопросы а тебе вместо подсказок указывают куда идти. Я же осознают что ТС не проделал никакой работы но я попытался ему хотябы как то намекнуть на логику кода. Постарался объяснить на доступном языке. Более того скажу . мы тут не делаем эталонные приборы. Не собираемся запускать линию производства. Человеку надо для учёбы. И думаю пусть код будет на костылях но если он будет работать и стабильно. То не обязательно извращаться. . все остальное придёт с опытом. А вы Logic как опытный программист могли бы и подсказать хотябы логику кода. Я понимаю книжки теория. Но например мне трудно понять написанное иногда проще когда тебе обьяснят на пальцах. Думаю и форум нужен для того чтоб советоваться а не посылать друг друга. Простите за прямолинейность

ОК. В прямолинейности нет ничего плохого. Плохое в другом, в желании перекинуть свою работу на плечи других. И не стоит удивлятся что окружающие этому сопротивляются. И дело не в том кто здесь больше программист. До програмирования необходимо определится с задачей, продумать её. А это посильно любому с достаточным IQ. Я не сомниваюсь, что Вы вполне смогли бы сами расписать необходимую последовательность действий максимально детально удобным себе способом. Т.е. составить алгоритм. С задачами такого рода как у Вас человек справляется очень хороше. Интуиция и жизненый опыт помогают. Надо только записать свои действия будь Вы на месте ардуино. Как бы вы определяли что "пока счетчик не насчитает определенное количество допустим кубиков"? Наверно запоминали бы сколько кубиков было и при появлении нового увеличивали это число на 1, затем сравнивали бы с заданым. А как определяли бы появление нового кубика? И т.д.  Но все эти действия - работа. Вполне посильная Вам, не требующая специальных знаний и умений, но не выполненая Вами. Вы не стали напрягатся, предпочли опубликовать пустой код. Пусть работают другие и нашару. Но на форуме помогают тем кто сам делает, а для желающих чтоб за них делали другие есть спецраздел. Вам наверно туда обратится разумней, и чесней.

///"Ардуино это хобби" Хобби - любимое занятие для получения удовольствия не приносящее дохода. Вы уверены что ардуино ваше любимое занятие? Как жеж вы им занимаетесь не умея писать программы. Может всеже будете прямыми до конца - возникла необходимость в решении задачи, но тратить время и деньги влом, пусть форум поработает ;)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Теперь напишем полностью содержимое класса учетчика

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс конвейер
class Cl_Transporter {
  protected:
    byte motorPin, lockPin, pullPin;
  public:
    /*конструктор*/
    Cl_Transporter(byte motorPin_, byte lockPin_, byte pullPin_)
      : motorPin(motorPin_), lockPin(lockPin_), pullPin(pullPin_) {}
    /*инициализация- вставить в setup*/
    void init() {}
    /*работа- вставить в loop*/
    void run() {}
    /*запустить конвейep*/
    void start() {}
    /*остановить конвейep*/
    void stop() {}
    /*разгрузить конвейep*/
    void swap() {}
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
    bool val, oldVal;
    byte num = 0, maxNum = 5; // сколько и мах кол-во предметов на конвейере
  public:
    /*конструктор*/
    Cl_Check(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT);
      oldVal = digitalRead(pin);
    }
    /*работа- вставить в loop*/
    void run() {
      val = digitalRead(pin);
      if (val && !oldVal) { // если произошел перепад ^\_
        oldVal = val;
        ++num;
        if (num >= maxNum) { // если кол-во предметов достигла максимума
          num = 0; Do();
        }
      }
      if (!val && oldVal) { // если произошел перепад _/^
        oldVal = val;
      }
    }
    /*режим5 предметов*/
    void mode5() {
      if (maxNum != 5) {
        maxNum = 5;
        if (num >= maxNum) {
          num = 0; Do();
        }
      }
    }
    /*режим10 предметов*/
    void mode10() {
      if (maxNum != 10) {
        maxNum = 10;
      }
    }
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    void (*Do)();// <-- это ее обработчик
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
  public:
    /*конструктор*/
    Cl_Btn(byte pin_, void (*Do_)())
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа- вставить в loop*/
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) Do();
      }
    }
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
void DoCheck() {
  Transporter.swap();
  Serial.println("Transporter Swap");
}
Cl_Check Check(/*пин счетчика*/6,/*обработчик*/&DoCheck);
void DoStart() {
  Serial.println("Transporter Start");
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Serial.println("Transporter Stop");
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Serial.println("DoMode5");
  Check.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Serial.println("DoMode10");
  Check.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  Transporter.init();
  Check.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}
void loop() {
  mill = millis();
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 2464 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 308 байт (15%) динамической памяти, оставляя 1740 байт для локальных переменных. Максимум: 2048 байт.
*/

ПС: Не надо думать что я воспылал благотворитьльностью к ТС. Это просто банальная "методичка" как писать простые программы под Ардуино по "простым задачам". И при этом я не вырываю волосы с головы или других частей. И самое главное не бегу за помошью на форум, что бы мне помогли со скетчем. Все делается по шагам , а которое я разложил до "пальцевого объяснения". И которое некоторые не любят, так как это объянение расжевано до примитивизма. 

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

С этим немного разобрался. Но вот содержимое функции Swap сделал через delay();

void swap() {
	
	digitalWrite(Motor, LOW);
	delay(500);
	digitalWrite(Lock, HIGH);
	delay(500);
	digitalWrite(Pull, HIGH);
	delay(1000);
	digitalWrite(Pull, LOW);
	delay(500);
	digitalWrite(Lock, LOW);
	delay(500);
	digitalWrite(Motor, HIGH);

}

, так как что то не пошло у меня через millis. 

Может что то не так делаю, но ни разу у меня не заработала задержка без delay();

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

pdjboy пишет:

С этим немного разобрался. Но вот содержимое функции Swap сделал через delay();

void swap() {
	
	digitalWrite(Motor, LOW);
	delay(500);
	digitalWrite(Lock, HIGH);
	delay(500);
	digitalWrite(Pull, HIGH);
	delay(1000);
	digitalWrite(Pull, LOW);
	delay(500);
	digitalWrite(Lock, LOW);
	delay(500);
	digitalWrite(Motor, HIGH);

}

, так как что то не пошло у меня через millis. 

Может что то не так делаю, но ни разу у меня не заработала задержка без delay();

Здесь у Вас в коде 5 задержек разной длительности.

Реализацию единственной задержки через millis() Вы можете сделать?

А теперь заводите переменную состояния, которая последовательно будет принимать значения от 0 до максимуму (например, до 4). Одновременно заводите массив констант на 5 значений. И текущее значение задержки (так, как Вы это делаете в случае единственой задержки) берете из массива с нужным индексом.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

void swap() {
  /*состояние 1*/
  digitalWrite(Motor, LOW);
  delay(500);
  /*состояние 2*/
  digitalWrite(Lock, HIGH);
  delay(500);
  /*состояние 3*/
  digitalWrite(Pull, HIGH);
  delay(1000);
  /*состояние 4*/
  digitalWrite(Pull, LOW);
  delay(500);
  /*состояние 5*/
  digitalWrite(Lock, LOW);
  delay(500);
  /*состояние 0*/
  digitalWrite(Motor, HIGH);
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну и заключительное . Понятно у меня конвейера нет , так что проверить не смогу. Да и к тем более там надо дотачивать под "окончательные хотелки" заказчика. А заказчики они такие... . Здесь я привел методику как без особого труда делать простые промышленные решения на Ардуине.


/**/
unsigned long mill; // переменная под millis()
typedef void (*pDo)(); // тип - функция обработчик
//--------------------------------
// класс мотор,класс заслонка,класс толкатель
#define ON_ HIGH
class Cl_Machine {
  protected:
    byte pin;
  public:
    /*конструктор*/
    Cl_Machine(byte pin_)
      : pin(pin_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, OUTPUT);
      OFF();
    }
    /*работа- вставить в loop*/
    void run() {}
    /*включить*/
    void ON() {
      digitalWrite(pin, ON_);
    }
    /*выключить*/
    void OFF() {
      digitalWrite(pin, !ON_);
    }
};
//--------------------------------------------
// класс конвейер
class Cl_Transporter {
  protected:
    Cl_Machine Motor, Lock, Pull;
    unsigned long past;
    byte state;//состояние конвейера
    /*устатановить конвейер в состояние*/
    void stand(byte state_) {
      state = state_;
      past = mill;
      switch (state) {
        case 0:
          Motor.ON();
          Serial.println("Motor ON");
          break;
        case 1:
          Motor.OFF();
          Serial.println("Motor OFF");
          break;
        case 2:
          Lock.ON();
          Serial.println("Lock ON");
          break;
        case 3:
          Pull.ON();
          Serial.println("Pull ON");
          break;
        case 4:
          Pull.OFF();
          Serial.println("Pull OFF");
          break;
        case 5:
          Lock.OFF();
          Serial.println("Lock OFF");
          break;
        default:
          Motor.OFF();
          Serial.println("Motor OFF");
      }
    }
  public:
    /*конструктор*/
    Cl_Transporter(byte pin1, byte pin2, byte pin3)
      : Motor(pin1), Lock(pin2), Pull(pin3) {}
    /*инициализация- вставить в setup*/
    void init() {
      Motor.init();
      Lock.init();
      Pull.init();
      stand(0);// вкл мотор
    }
    /*работа- вставить в loop*/
    void run() {
      if (state == 1 && mill - past >= 500) stand(2);
      if (state == 2 && mill - past >= 500) stand(3);
      if (state == 3 && mill - past >= 500) stand(4);
      if (state == 4 && mill - past >= 1000)stand(5);
      if (state == 5 && mill - past >= 500)stand(0);
    }
    /*запустить конвейep*/
    void start() {
      if (state == 6) stand(0);// вкл мотор
    }
    /*остановить конвейep*/
    void stop() {
      if (state == 0) stand(6);// выкл мотор
    }
    /*разгрузить конвейep*/
    void swap() {
      if (state == 0) stand(1);// вкл разгрузку конвейера
    }
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
    byte pin; //<-- это переменая ноги
    pDo Do;   //<-- это ее обработчик
    bool val, oldVal;
    byte num = 0, maxNum = 5; // сколько и мах кол-во предметов на конвейере
  public:
    /*конструктор*/
    Cl_Check(byte pin_, pDo Do_): pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT);
      oldVal = digitalRead(pin);
    }
    /*работа- вставить в loop*/
    void run() {
      val = digitalRead(pin);
      if (val && !oldVal) { // если произошел перепад ^\_
        oldVal = val;
        ++num;
        if (num >= maxNum) { // если кол-во предметов достигла максимума
          num = 0; Do();
        }
      }
      if (!val && oldVal) { // если произошел перепад _/^
        oldVal = val;
      }
    }
    /*режим5 предметов*/
    void mode5() {
      if (maxNum != 5) {
        maxNum = 5;
        if (num >= maxNum) {
          num = 0; Do();
        }
      }
    }
    /*режим10 предметов*/
    void mode10() {
      if (maxNum != 10) {
        maxNum = 10;
      }
    }
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    pDo Do;// <-- это ее обработчик
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
  public:
    /*конструктор*/
    Cl_Btn(byte pin_, pDo Do_)
      : pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа- вставить в loop*/
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) Do();
      }
    }
};
//---Компоновка-----------------------------
Cl_Transporter Transporter(/*пин Мотора*/7,/*пин Шторки*/8,/*пин Толкателя*/9);
void DoCheck() {
  Transporter.swap();
  Serial.println("Transporter Swap");
}
Cl_Check Check(/*пин счетчика*/6,/*обработчик*/&DoCheck);
void DoStart() {
  Serial.println("Transporter Start");
  Transporter.start();
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/&DoStart);
void DoStop() {
  Serial.println("Transporter Stop");
  Transporter.stop();
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/&DoStop);
void DoMode5() {
  Serial.println("DoMode5");
  Check.mode5();
}
Cl_Btn Btn3(/*пин*/4,/*обработчик*/&DoMode5);
void DoMode10() {
  Serial.println("DoMode10");
  Check.mode10();
}
Cl_Btn Btn4(/*пин*/5,/*обработчик*/&DoMode10);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  Transporter.init();
  Check.init();
  Btn1.init();
  Btn2.init();
  Btn3.init();
  Btn4.init();

}
void loop() {
  mill = millis();
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}
/* Скетч использует 3242 байт (10%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 367 байт (17%) динамической памяти, оставляя 1681 байт для локальных переменных. Максимум: 2048 байт.
*/

ПС: Простите за окончательное причесывание кода.

saftik
Offline
Зарегистрирован: 08.04.2015

Logik пишет:

saftik пишет:
Я не заявлял себя программистом.

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

///"Ардуино это хобби" Хобби - любимое занятие для получения удовольствия не приносящее дохода. Вы уверены что ардуино ваше любимое занятие? Как жеж вы им занимаетесь не умея писать программы. Может всеже будете прямыми до конца - возникла необходимость в решении задачи, но тратить время и деньги влом, пусть форум поработает ;)

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

 

Logik
Онлайн
Зарегистрирован: 05.08.2014

Да, извините, это  разумеется к ТС относится. Вы честно попробовали помоч, хоть и не очень удачно. Проблема - delay.

Вобще обходить его не сложно, например так для функции knopki

byte knopki(byte nt)
{
  static byte t;
  static byte stat=0;

  if(stat)
  {
    if(nt-t>=100)
     return 1;
     
    switch(stat)
    {
      case 1: flag_motor = 1;break;
      case 2: flag_motor = 0;break;
      case 3: couter = 5;break;
      case 4: couter = 10;break;
    }
    stat = 0;
    return 0;
  }
  else
  {
   if (SW_Start == LOW) stat = 1;
   if (SW_Stop == LOW) stat = 2;
   if (SW_5 == LOW) stat = 3;
   if (SW_10 == LOW) stat = 4;

   if(stat) t = nt;
   return 1;
  }

}

loop ()
{
 byte time;

 time=millis();

 if(knopki(time))
 {
   //здесь делаем то что нужно во время паузы
 }
 else
 {
   //здесь делаем то что нужно во время ожидания нажатия кнопки
 }
 //здесь делаем то что нужно всегда
}

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


void knopki()
{

   if (SW_Start == LOW) flag_motor = 1;
   if (SW_Stop == LOW) flag_motor = 0;
   if (SW_5 == LOW) couter = 5;
   if (SW_10 == LOW) couter = 10;

}

loop ()
{
 byte time;
 static byte t;

 time=millis();

 if((byte)(time-t)>=100)
 {
   t=time;
   knopki();     
 }

}

Проще просто некуда.

Тоже не проверял, но думаю мелкие огрехи Вы и сами почистите если чё.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

arduino328 пишет:

За рулём сидят роботы, управляемые Ардуино :)

А гаишники, видимо, stm управляются? Так вот откуда эти вечные срачи! А я то думал ...

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Спасибо огромное, кажется меньшая половина материала понята и усвоена. Классы и объекты еще учить и учить. Ну и еще на прямую портами управлять, чтобы как бы быстрее и правильнее было. Мой вариант, как бы пока что без ООП. Но все в будущем. Учится, учится и потом еще перед сном форум покурить.

 

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну без ООП не обойтись . В даном случае ООП = объектно-ориентированое проектирование. Когда надо прорабатывать ТЗ до мельчальших нюансов.  Но так как все не учтешь, вот и выработал такой подход как собирать новые скетчи из проверенных старых,которые нормально идут без конфликта.

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Хм, не пойму, почему если я заменяю ардуиновские "8,9,10" на прямые обращения к регистру DDRx, выхода на мотор, шторку и разргузку работают а входные сигналы нет?(

И если не тяжело, подскажите как через PINx читать состояние кнопок и датчик в моем случае? Препод закапризничал чтобы на прямую к регистрам портов были обращения.

unsigned long mill; // переменная под millis()
typedef void (*pDo)(); // тип - функция обработчик											

// класс мотор,класс заслонка,класс толкатель
#define ON_ HIGH
class Cl_Machine {
  protected:
    byte pin;
  public:
    /*конструктор*/
    Cl_Machine(byte pin_)
      : pin(pin_) {}
    
    void init() {      
      OFF();
    } 
       
    void ON() {
      digitalWrite(pin, ON_);
    }

    void OFF() {
      digitalWrite(pin, !ON_);
    }
};
//--------------------------------------------
// класс конвейер
class Cl_Transporter {
  protected:
    Cl_Machine Motor, Lock, Pull;
    unsigned long past;
    byte state;//состояние конвейера
    /*устатановить конвейер в состояние*/
    void stand(byte state_) {
      state = state_;
      past = mill;
      switch (state) {
        case 0:
           PORTB = 0x1;                 //Motor ON
          Serial.println("Motor ON");
          break;
        case 1:
           PORTB = 0x00;                //Motor OFF
          Serial.println("Motor OFF");
          break;
        case 2:
          PORTB = 0x2;                  //Lock ON
          Serial.println("Lock ON");
          break;
        case 3:
          PORTB = 0x6;                  //Pull ON
          Serial.println("Pull ON");
          break;
        case 4:
          PORTB = 0x2;                 //Pull OFF
          Serial.println("Pull OFF");
          break;
        case 5:
          PORTB = 0x00;                 //Lock OFF
          Serial.println("Lock OFF");
          break;
        default:
          PORTB = 0x00;                 //Motor OFF
          Serial.println("Motor OFF");
      }
    }
  public:
    /*конструктор*/
    Cl_Transporter(byte pin1, byte pin2, byte pin3)
      : Motor(pin1), Lock(pin2), Pull(pin3) {}
    /*инициализация- вставить в setup*/
    void init() {
      
      stand(0);// вкл мотор
    }
    /*работа- вставить в loop*/
    void run() {
      if (state == 1 && mill - past >= 800) stand(2);
      if (state == 2 && mill - past >= 800) stand(3);
      if (state == 3 && mill - past >= 800) stand(4);
      if (state == 4 && mill - past >= 1000)stand(5);
      if (state == 5 && mill - past >= 800) stand(0);
    }
    /*запустить конвейep*/
    void start() {
      if (state == 6) stand(0);// вкл мотор
    }
    /*остановить конвейep*/
    void stop() {
      if (state == 0) stand(6);// выкл мотор
    }
    /*разгрузить конвейep*/
    void swap() {
      if (state == 0) stand(1);// вкл разгрузку конвейера
    }
};
//----------------------------
//класс учетчик
class Cl_Check {
  protected:
    byte pin; //<-- это переменая ноги
    pDo Do;   //<-- это ее обработчик
    bool val, oldVal;
    byte num = 0, maxNum = 5; // сколько и мах кол-во предметов на конвейере
  public:
    /*конструктор*/
    Cl_Check(byte pin_, pDo Do_): pin(pin_), Do(Do_) {}
    /*инициализация- вставить в setup*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
      oldVal = digitalRead(pin);
    }
    /*работа- вставить в loop*/
    void run() {
      val = digitalRead(pin);
      if (val && !oldVal) { // если произошел перепад ^\_
        oldVal = val;
        ++num;
        Serial.println(num);
        if (num >= maxNum) { // если кол-во предметов достигла максимума
          num = 0; Do();
        }
      }
      if (!val && oldVal) { // если произошел перепад _/^
        oldVal = val;
      }
    }
    /*режим5 предметов*/
    void mode5() {
      if (maxNum != 5) {
        maxNum = 5;
        if (num >= maxNum) {
          num = 0; Do();
        }
      }
    }
    /*режим10 предметов*/
    void mode10() {
      if (maxNum != 10) {
        maxNum = 10;
      }
    }
};
//--------------------------------
// класс кнопка
class Cl_Btn {
  protected:
    byte pin; //<- это переменая ноги
    pDo Do;// <-- это ее обработчик
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
  public:
    
    Cl_Btn(byte pin_, pDo Do_)
      : pin(pin_), Do(Do_) {}
   
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) Do();
      }
    }
};

Cl_Transporter Transporter(DDRB=0x1,DDRB=0x2,DDRB=0x4);          

void DoCheck() {
  Transporter.swap();
  Serial.println("Transporter Swap");
}

Cl_Check Check(DDRD=0x40,&DoCheck);		  								 

void DoStart() {
  Serial.println("Transporter Start");
  Transporter.start();}
Cl_Btn Btn1(DDRD=0x4,&DoStart);					  					

void DoStop() {
  Serial.println("Transporter Stop");						      
  Transporter.stop();}
Cl_Btn Btn2(DDRD=0x8,&DoStop);											

void DoMode5() {												  
  Serial.println("DoMode5");
  Check.mode5();}
Cl_Btn Btn3(DDRD=0x10,&DoMode5);															

void DoMode10() {
  Serial.println("DoMode10");
  Check.mode10();}
Cl_Btn Btn4(DDRD=0x20,&DoMode10);										

//---main-----------------------------
void setup() {
  
  DDRB = 0xFF;                     
  PORTB = 0x00;                     
  
  DDRC = 0x00;                     
  PORTC = 0xFF;                     
  
  DDRD = 0x00;                      
  PORTD = 0xFF;                     
  Serial.begin(9600);              
  
}
void loop() {
  mill = millis();  
  Transporter.run();
  Check.run();
  Btn1.run();
  Btn2.run();
  Btn3.run();
  Btn4.run();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Так вы основ не знаете. Дело в том что пины придуманы для новичков Ардуинщиков, которые банально нихрена не знают ни об языке Си ни о процессорах. Для управления пином надо знать адреса трех!!! регистров .  А что такое адрес это указатель . а пин это число. Это очень разные вещи . Вы же не будете мерять напряжение в литрах. А мощнось  установки рулеткой. Так и там . #175

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

qwone пишет:

Для управления пином надо знать адреса трех!!! регистров . 

DDRx = Регистр направления передачи данных

PORTx = Регистр вывода данных

PINx =  Регистр ввода данных

это понятно, тут как бы не надо быть гуру и много знать.

Вопро почему оно не фурычит, точнее не везде в скетче.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

pdjboy пишет:

это понятно, тут как бы не надо быть гуру и много знать.

Вопро почему оно не фурычит, точнее не везде в скетче.

Вам был дан вполне себе правильный ответ:

qwone пишет:

так вы основ не знаете. 

Вы сейчас хитрым образом, скопипастив код qwone, дописав туда неизвестно что, хотите, чтобы вам поправили его до рабочей версии? Не совсем тонко, что называется. Идите в гугль, набирайте в строке поиска "Работа с портами AVR" и сделайте над собой усилие, изучив хотя бы парочку (заметьте, я не говорю о даташитах - а просто о вводных статьях).

Только там можно чему-то научиться. Поэтому препод не капризничает, а прав на 100500% - вам, долбанам, так и надо знания в головы вкладывать.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

pdjboy пишет:

DDRx = Регистр направления передачи данных

PORTx = Регистр вывода данных

PINx =  Регистр ввода данных

это понятно, тут как бы не надо быть гуру и много знать.

Вопро почему оно не фурычит, точнее не везде в скетче.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

pdjboy пишет:
тут как бы не надо ... много знать.
Как видите, как бы, надо. Много - не много, но больше, чем знаете Вы. Учитесь.