Ви не увійшли.
Похоже тема напомнила мне это место.
А ты что больше всего любишь делать?
— Это всё я тоже люблю,— сказал Кристофер Робин,— но что больше всего я люблю делать — это...
— Ну, ну?
— Ничего.
— А как ты это делаешь? — спросил Пух после очень продолжительного размышления.
— Ну, вот, спросят, например, тебя, как раз когда ты собираешься это делать: “Что ты собираешься делать, Кристофер Робин?”, а ты говоришь: “Да ничего”, а потом идёшь и делаешь.
— А, понятно! — сказал Пух.
Код компилируется, но я не проверял. Одна кнопка запускает, вторая останавливает. Разберетесь напишите и себе.
/*
*/
//---------------Cl_Led---------
//класс Cl_Led управление светодиодом
class Cl_Led {
byte _pin;//нога светодиода
bool _led;// уровень на выводе светодиода
byte _stat ; //0 готовность к взводу / 1 время до импульса / 2 импульс/3 конец
uint32_t _time_start, _time_pulse;
uint32_t _past = 0 ;
public:
// конструктор класса
Cl_Led(byte pin): _pin(pin) {}
// метод setup()
void setup() {
pinMode(_pin, OUTPUT);
digitalWrite(_pin, _led = 0);
_stat = 0;
}
// метод loop()
void loop() {
if (_stat == 1 & millis() - _past >= _time_start) {
_past = millis();
digitalWrite(_pin, _led = 1);
_stat == 2;
}
if (_stat == 2 & millis() - _past >= _time_pulse) {
_past = millis();
digitalWrite(_pin, _led = 0);
_stat == 3;
}
}
void pulse(uint32_t time_start, uint32_t time_pulse) {
_time_start = time_start;
_time_pulse = time_pulse;
}
void stop() {
digitalWrite(_pin, _led = 0);
_stat == 3;
}
};
//---------------Cl_Btn--------
//класс кнопка подключ на питание через резистор 10кОм
class Cl_Btn {
byte pin; // номер ноги на кнопке
void (* Do)();// указатель на обработчик
bool btn, btn_old;
bool bounce = 0; // антидребезговый флаг
uint32_t past = 0 ;
public:
// конструктор класса
Cl_Btn( byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {}
// метод setup()
void setup() {
pinMode(pin, INPUT);// подключить кнопку 1 с подтяжкой
btn = digitalRead(pin); // прочитать реальное значение на выводе};
}
// метод loop()
void loop() {
if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
bounce = 1; // выставить флаг
past = millis(); // сделать временую засветку
}
else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
bounce = 0; // то снять флаг
btn_old = btn ;
btn = digitalRead(pin) ; // прочитать реальное значение на выводе
if (!btn_old && btn) Do();
}
}
};
//--------------компоновка------------
Cl_Led Led1(/*пин*/12);
void Do_Btn1() {
Led1.pulse(1000ul * random(10, 60) , 2000);
}
Cl_Btn Btn1(/*пин*/10,/*обработчик*/Do_Btn1);
void Do_Btn2() {
Led1.stop();
}
Cl_Btn Btn2(/*пин*/11,/*обработчик*/Do_Btn2);
//------------main()--------------
void setup() {
Led1.setup();
Btn1.setup();
Btn2.setup();
}
void loop() {
Led1.loop();;
Btn1.loop();
Btn2.loop();
}
Спасибо , у меня все хорошо. Представим гипотетическую ситуацию. Человек просит порезать , к примеру торт. Вроде все привычно. Смотрите и видите, что это жидкий кисель в кастрюле. Вроде глупо его резать на кусочки. Говоришь человеку прямо, что это не торт и его никто не порежет, да и неизвестно как это резать. Человек обижается. Говорит, что да он не повар, и киевский торт у него не получился, зато получился наполеон. Вот его и надо порезать.
Разумеется это не форум кулинарии, но искать в гугле или на ютубе вроде уже вменяемый человек может. Ладно скину немного ссылок сюда.
https://www.youtube.com/watch?v=gRSYxXbjnCg
https://www.youtube.com/watch?v=CqsuqdI3QJI
https://www.youtube.com/watch?v=ojhhQqMy-9U
А у вас здесь нет кода, обработки енкодера. А есть хрен знает что. И значить обнулять это хрен знает кто и хрен знает как.
const byte Sens_pin = /*нога сенсора*/A2;
const byte Relay_pin =/*нога реле*/ 9;
void setup() {
pinMode ( Relay_pin , OUTPUT );// реле включения питания
digitalWrite( Relay_pin , 1 ); // выключаю реле
}
void loop() {
delay ( 500 );
int Sens = analogRead(Sens_pin);
if ( Sens < 20) digitalWrite( Relay_pin , 0 ); //если стало сухо, то вкл реле
if ( Sens > 25) digitalWrite( Relay_pin , 1 ); //если стало сильно влажно, то выкл реле
}
А хрен вас "Колумбов" поймешь. Или вы Сусанины , Моисеи доморощеные . Может у вас сам процесс заблудиться в Лесу "Три Сосны" прет. Вы хотели посмотреть мой код - Ловите. А как вы это назовете мне глубоко начхать.
/*.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();
}
именно для этого огромного стада и сделана дуня с её вирингом и библиотеками, которые на 100% подходят для решения огромного количества различных задач и не требуют глубокого изучения программирования.
большинству вообще достаточно Джереми Блюма и ничего в этом страшного и плохого нет.кому нужно - идут дальше, читают другие книги, учатся.
а для правильных кодеров есть другие форумы, зачем им копашиться в стаде, где никто ничего не знает и не понимает...
Проблема из этого стада и его мышления вырваться. А серьезные игрушки требуют серьезного программирования.Или серьезной "программной прокладки" что бы это стадо так же там "программировало", как на дуне. А то что эта прокладка жрет дофига ресурсов и криво написана, так на то она и "прокладка".
я и не знал что есть целое направление ардуино - программистов)))
всегда был уверен что есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами.
Я не знал что у меня, есть огромная семья...
Да , есть просто программисты пишущие на с++ и работающие с avr микроконтроллерами, а есть огромное "стадо" программистов пишущих в среде Ардуино на обрезаном Си. Не программно, не аппаратно обрезаном,а на морально-мол так никто не пишет. И навык написания они берут от образцов демонстрашек Ардуина и Адафрут библиотек. Которые замечательно работают, когда залиты индивидуально а МК. Вот для реализации "паралельной" работы демонстрашек и нужны (а) дублирующий камень (б) расширенные аппаратные возможности МК поддерживающие "многозадачность". А то что парралельную работу некритичных к скорости работы устройств можно организовать и на одном МК, считают за ересь.
ПС: По теме. ТС , вы слышали про millis() и как с помощью него распределять работу асинхронно работающих частей программы или все так же будете топтаться на месте.
А зачем вам мои библиотеки, вы же блин "дубоваты". Вы или ищите аппаратные возможности . Или без "аппаратных возможностей" у вас "многозадачность" сильно "озадачивается".
ПС: А мне приходится искать свой подход. А пол-дела народу не показывают.
Я не могу заставить асинхронно работать и весы и шаговик. Возможно это особенность самой Arduino или я не понимаю как правильно писать код.
Скорее всего в Ардуино у ардуино-программистов отсутсвует Школа программирования. Это значит, что на Ардуино можно писать асинхроноработающие программы, но у стандартного ардуинщика отсутсвует уровень знаний. Особенность маркетинга Ардуино и ничего личного.
ПС: Это же касается и библиотек на Ардуно. Зачем напрягаться и писать хорошо, народ на Ардуне сидит "дубоватый".
Сорри на не по теме. Вот код недо графический интерфейс. 3 графические кнопки на экране и окошко для сообщение. кликаешь по кнопкам сообщение меняется. Вроде программа не о чем Экран Нокия 5110 и аналоговый джойстик вместо мышки.
/*Cl_aJoystick_v3.ino
синий экран
Serial clock out 5(SCLK) -->3
Serial data out 4(DIN) -->4
Data/Command select 3(D/C) -->5
LCD chip select 2(CS) -->6
LCD reset 1(RST) -->7
6(Vcc) -->3.3V
7(BL) -->3.3V
8(GND) -->GND
Джойстик (GND) --> GND
(+5V) --> +5V
(VRx) --> A0
(VRy) --> A1
(SW) --> A2
*/
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(/*SCLK*/3,/*DIN*/4,/*D/C*/5,/*CS*/6,/*RST*/7);
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_aJoystick-------------------------------------------------------
const int delta = 5; // колебание значения на аналоговых выходах, которые можно игнорировать
class Cl_aJoystick {
byte VRx_pin ; // номер ноги на выводе VRx
byte VRy_pin ; // номер ноги на выводе VRy
byte SW_pin ; // номер ноги на выводе SW
void (* Do_SW)(byte, byte); //указатель на обработчик кнопки SW
int VRx_old; // старые значение на канале X
int VRy_old; // старые значение на канале Y
bool SW, SW_old;
bool bounce_VRx = 0, bounce_VRy = 0, bounce_SW = 0; // антидребезговый флаг
uint32_t past_VRx = 0, past_VRy = 0 , past_SW = 0 ;
public:
byte x, y ; // положение надписи
char * txt = NULL ; // указатель на надпись
// указатель на следующий элемент
Cl_aJoystick *pnt;
// конструктора
Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)(byte, byte));
void setup() {
pinMode(VRx_pin, INPUT) ;// подключить вывод VRx
pinMode(VRy_pin, INPUT) ;// подключить вывод VRy
pinMode(SW_pin , INPUT_PULLUP);// подключить вывод SW с подтяжкой
VRx = analogRead (VRx_pin);
x = map( VRx, 0, 1023, 0, 83);
VRy = analogRead (VRy_pin);
y = map( VRy, 0, 1023, 0, 47);
SW = digitalRead(SW_pin) ;
}
// setup()
void loop() {
// проверяем аналог канал х
int analog = analogRead (VRx_pin);
if (! bounce_VRx && (VRx < analog - delta || VRx > analog + delta)) { // если прошел фронт изм на выводн
bounce_VRx = 1; // выставить флаг
past_VRx = millis(); // сделать временую засветку
} else if ( bounce_VRx && millis() - past_VRx >= 5 ) { // если прошло антидребезговое время
bounce_VRx = 0; // то снять флаг
VRx_old = VRx ;
VRx = analog ; // прочитать реальное значение на выводе
x = map( VRx, 0, 1023, 0, 83);
}
// проверяем аналог канал y
analog = analogRead (VRy_pin);
if (! bounce_VRy && (VRy < analog - delta || VRy > analog + delta)) { // если прошел фронт изм на выводн
bounce_VRy = 1; // выставить флаг
past_VRy = millis(); // сделать временую засветку
} else if ( bounce_VRy && millis() - past_VRy >= 5 ) { // если прошло антидребезговое время
bounce_VRy = 0; // то снять флаг
VRy_old = VRy ;
VRy = analog ; // прочитать реальное значение на выводе
y = map( VRy, 0, 1023, 0, 47);
}
// проверяем кнопку SW
if (! bounce_SW && SW != digitalRead(SW_pin)) { // если прошел фронт изм на выводн
bounce_SW = 1; // выставить флаг
past_SW = millis(); // сделать временую засветку
} else if ( bounce_SW && millis() - past_SW >= 5 ) { // если прошло антидребезговое время
bounce_SW = 0; // то снять флаг
SW_old = SW ;
SW = digitalRead(SW_pin) ; // прочитать реальное значение на выводе
if (! SW_old && SW) Do_SW(x, y);
}
}
int VRx ; // значение на канале X
int VRy ; // значение на канале Y
};
//-----Cl_Label-------------------------------------------------------------
class Cl_Label {
public:
byte x, y, w, h; // геомет размеры поз x,y w-ширина h-высота
char *txt = NULL;
// указатель на следующий элемент
Cl_Label *pnt;
// конструктора
Cl_Label(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt);
void setup() {
}
// setup()
void loop() {
}
};
//-----Cl_Btn-------------------------------------------------------------
class Cl_Btn {
public:
void (* Do)(); // указатель на обработчик клик
byte x, y, w, h; // геомет размеры поз x,y w-ширина h-высота
char *txt = NULL;
// указатель на следующий элемент
Cl_Btn *pnt;
// конструктора
Cl_Btn(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt, void (* _Do)());
void setup() {
}
// setup()
void loop() {
}
};
//-----Cl_Sys----------------------------------------------------------------
class Cl_Sys {
uint32_t past = 0;
public:
Cl_aJoystick *Start_aJoystick = NULL;
Cl_Label *Start_Label = NULL;
Cl_Btn *Start_Btn = NULL;
Cl_Sys() {}
// setup()
void setup() {
display.begin(); // Инициализация дисплея
display.setContrast(60); // Устанавливаем контраст
display.setTextColor(BLACK); // Устанавливаем цвет текста
display.setTextSize(1); // Устанавливаем размер текста
display.clearDisplay(); // Очищаем дисплей
display.display();
for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->setup();
for (Cl_Label *i = Start_Label ; i != NULL; i = i->pnt) i->setup();
for (Cl_Btn *i = Start_Btn ; i != NULL; i = i->pnt) i->setup();
}
// loop()
void loop() {
for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->loop();
for (Cl_Label *i = Start_Label ; i != NULL; i = i->pnt) i->loop();
for (Cl_Btn *i = Start_Btn ; i != NULL; i = i->pnt) i->loop();
// вывод обновленой информации раз в 0.5 сек
if (millis() - past >= 100) {
past = millis();
display.clearDisplay(); // Очищаем дисплей
// вывод Label
for (Cl_Label *i = Start_Label; i != NULL; i = i->pnt) {
display.setCursor(i->x + 2, i-> y + 2);
display.print(i->txt);
display.drawRect(i->x, i->y, i->w, i->h, BLACK);
}
// вывод Btn
for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) {
display.setCursor(i->x + 2, i-> y + 2);
display.print(i->txt);
display.drawRect(i->x, i->y, i->w, i->h, BLACK);
}
// вывод джойстика
for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) {
display.setCursor(i->x, i-> y);
display.print(i->txt);
display.display();
}
}
}
void onClick(byte onClickX, byte onClickY) {
for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt)
if (i->x <= onClickX && onClickX < (i->x + i->w) && i->y <= onClickY && onClickY < (i->y + i->h))i->Do();
}
} Sys;
//---------описание классов------------
Cl_aJoystick::Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)(byte, byte))
: VRx_pin(_1pin), VRy_pin(_2pin), SW_pin(_3pin), Do_SW(_Do_SW) {
x = 0; y = 0; txt = "^";
pnt = Sys->Start_aJoystick;
Sys->Start_aJoystick = this;
}
Cl_Label::Cl_Label(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt)
: x(_x), y(_y), w(_w), h(_h), txt(_txt) {
pnt = Sys->Start_Label;
Sys->Start_Label = this;
}
Cl_Btn::Cl_Btn(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt, void (* _Do)())
: x(_x), y(_y), w(_w), h(_h), txt(_txt) , Do(_Do) {
pnt = Sys->Start_Btn;
Sys->Start_Btn = this;
}
//----------Компоновка---------------------
void Do_SW(byte onClickX, byte onClickY) {
Sys.onClick(onClickX, onClickY);
}
Cl_aJoystick *aJoystick = new Cl_aJoystick(&Sys,/*VRx*/A0,/*VRy*/A1,/*SW*/A2,/*обработчик наж SW*/Do_SW); // создать aJoystick_1
Cl_Label *Label = new Cl_Label (&Sys,/*x*/0 ,/*y*/0 ,/*w*/48,/*h*/11,/*текст*/"Label 1"); // создать Label_1
void Do_Btn1() {
Label->txt = "Do_Btn1";
}
void Do_Btn2() {
Label->txt = "Do_Btn2";
}
void Do_Btn3() {
Label->txt = "Do_Btn3";
}
Cl_Btn *Btnl = new Cl_Btn(&Sys,/*x*/0 ,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn1",/*обработчик^\_*/Do_Btn1);// создать кнопку 1
Cl_Btn *Btn2 = new Cl_Btn(&Sys,/*x*/28,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn2",/*обработчик^\_*/Do_Btn2);// создать кнопку 2
Cl_Btn *Btn3 = new Cl_Btn(&Sys,/*x*/56,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn3",/*обработчик^\_*/Do_Btn3);// создать кнопку 3
//-----------Main()-----------------------
void setup() {
Sys.setup();
}
void loop() {
Sys.loop();
}
Ладно. С пацаном и его проектом все ясно. Я вот скеч нарисовал. Зацените.
/*Cl_LcdBtn_in_Nokia5110.ino
* синий экран
Serial clock out 5(SCLK) -->3
Serial data out 4(DIN) -->4
Data/Command select 3(D/C) -->5
LCD chip select 2(CS) -->6
LCD reset 1(RST) -->7
6(Vcc) -->3.3V
7(BL) -->3.3V
8(GND) -->GND
кнопка 1 (Btn_1) -->8
кнопка 2 (Btn_2) -->9
кнопка 3 (Btn_3) -->10
*/
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(/*SCLK*/3,/*DIN*/4,/*D/C*/5,/*CS*/6,/*RST*/7);
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Label-----------------
class Cl_Label {
public:
byte x, y ; // положение надписи
char * txt = NULL ; // указатель на надпись
// указатель на следующий элемент
Cl_Label *pnt;
// конструктор
Cl_Label(Cl_Sys *Sys, char *_txt , byte _x , byte _y );
void setup() {
}
// setup()
void loop() {
}
// сделать надпись
void Caption(char *_txt) {
txt = _txt;
}
};
//-----Cl_LcdBtn-----------------
class Cl_LcdBtn {
byte pin; // номер ноги на кнопке
bool btn, btn_old;
bool bounce = 0; // антидребезговый флаг
uint32_t past = 0 ;
public:
void (* Do1)(), (* Do2)(); // указатель на обработчики нажатия,отжатия
byte x, y ; // положение надписи
char * txt = NULL ; // указатель на надпись
// указатель на следующий элемент
Cl_LcdBtn *pnt = NULL;
// конструктор
Cl_LcdBtn(Cl_Sys *Sys, byte _pin, void (* _Do1)(), void (* _Do2)(), char *_txt , byte _x , byte _y );
void setup() {
pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
btn = digitalRead(pin); // прочитать реальное значение на выводе};
}
// setup()
void loop() {
if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
bounce = 1; // выставить флаг
past = millis(); // сделать временую засветку
}
else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
bounce = 0; // то снять флаг
btn_old = btn ;
btn = digitalRead(pin) ; // прочитать реальное значение на выводе
if (btn_old && !btn) Do1(); // если произошло нажатие
if (!btn_old && btn) Do2(); // если произошло отжатие
}
}
// сделать надпись
void Caption(char *_txt) {
txt = _txt;
}
};
//-----Cl_Sys-----------------
class Cl_Sys {
uint32_t past = 0;
public:
Cl_Label *Startl_Label = NULL;
Cl_LcdBtn *Start_Btn = NULL;
Cl_Sys() {}
// setup()
void setup() {
display.begin(); // Инициализация дисплея
display.setContrast(60); // Устанавливаем контраст
display.setTextColor(BLACK); // Устанавливаем цвет текста
display.setTextSize(1); // Устанавливаем размер текста
display.clearDisplay(); // Очищаем дисплей
display.display();
for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) i->setup();
for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) i->setup();
}
void loop() {
for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) i->loop();
// вывод обновленой информации раз в 0.5 сек
if (millis() - past >= 500) {
past = millis();
display.clearDisplay(); // Очищаем дисплей
for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) {
display.setCursor(i->x, i-> y);
display.print(i->txt);
}
for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) {
display.setCursor(i->x, i-> y);
display.print(i->txt);
}
display.display();
}
}
} Sys;
//---------описание классов------------
Cl_Label::Cl_Label(Cl_Sys *Sys, char *_txt , byte _x = 0 , byte _y = 0): x(_x), y(_y) {
txt = _txt,
pnt = Sys->Startl_Label;
Sys->Startl_Label = this;
}
Cl_LcdBtn::Cl_LcdBtn(Cl_Sys *Sys, byte _pin, void (* _Do1)(), void (* _Do2)(), char *_txt , byte _x = 0 , byte _y = 0)
: pin(_pin), Do1(_Do1), Do2(_Do2), txt(_txt), x(_x), y(_y) {
pnt = Sys->Start_Btn;
Sys->Start_Btn = this;
}
//----------Компоновка---------------------
Cl_Label *Label = new Cl_Label(&Sys,/*текст*/"Label",/*поз х*/0,/*поз y*/0); // создать объект Лабел
void Do1_Btn1();// объявим что есть такие обработчики
void Do2_Btn1();
void Do1_Btn2();
void Do2_Btn2();
void Do1_Btn3();
void Do2_Btn3();
Cl_LcdBtn *Btn_1 = new Cl_LcdBtn(&Sys,/*пин*/8 ,/*обработчик*/Do1_Btn1,/*обработчик*/Do2_Btn1,/*текст*/"1of",/*поз х*/0*8 ,/*поз y*/5*8); // создать кнопку Btn_1
Cl_LcdBtn *Btn_2 = new Cl_LcdBtn(&Sys,/*пин*/9 ,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*текст*/"2of",/*поз х*/4*8 ,/*поз y*/5*8); // создать кнопку Btn_2
Cl_LcdBtn *Btn_3 = new Cl_LcdBtn(&Sys,/*пин*/10,/*обработчик*/Do1_Btn3,/*обработчик*/Do2_Btn3,/*текст*/"3of",/*поз х*/8*8 ,/*поз y*/5*8); // создать кнопку Btn_3
void Do1_Btn1() {
Label->Caption("Btn 1");
Btn_1->Caption("1on");
}
void Do2_Btn1() {
Btn_1->Caption("1of");
}
void Do1_Btn2() {
Label->Caption("Btn 2");
Btn_2->Caption("2on");
}
void Do2_Btn2() {
Btn_2->Caption("2of");
}
void Do1_Btn3() {
Label->Caption("Btn 3");
Btn_3->Caption("3on");
}
void Do2_Btn3() {
Btn_3->Caption("3of");
}
//-----------Main()-----------------------
void setup() {
Sys.setup();
}
void loop() {
Sys.loop();
}
У парнишки "звездная болезнь", его лечить надо, а не быть снисходительным. Он же вырастет, и "болезнь вырастет".
Так даже проблема не в экономии. А в детском подходе к проекту. Это ух ты я какую штуку забабахал, не каждый взрослый сможет. А вот точно не каждый взрослый может подойти по взрослому к такому проекту. Одно дело сделать, а другое расчитать экономическую целесообразность, заинтересовать людей этим проектом и прочее прочее. А то будет как у Ростика с картоными танками для ВСУ.
Основная проблема в команде scrollMessage(scrollText2); Она как delay() . Пока она работает остальное стоит. А когда она закончится начнет работать все остальное по очереди. До следущих тормозов похожих на delay() . Это не Ардуино виновата. Это даунский подход к программироваю на Си на этой платформе. Вижу несколько путей: есть визуал программирование на Ардуине. Хотя так кривой код, но тормозов delay() поменьше. Или же учить глубже Си->Cи++ -> ООП . Я выбрал 2 путь. Ничего по этому огрызку программы не скажу, так как это огрызок. А у меня хрустальный шар затерялся.
Если вы покупаете машинку в детских товарах, а потом норовите сесть за руль и ездить по нормальным дорогам, то всем покажет, что вы идиот. Так вот и программирование на Ардуине. Оно расчитано на детей. Для проектов посложнее надо получше разбираться в Си и программированиию
Надо 3 кнопки : + - Импульс
1 индикатор для отображения длительности импульса.
Если расуждать еще глубже, то основная работа программиста не писать программы, а сопровождать их. Сопровождение это адаптирование какой-то программы под текущие требования. Возмем к примеру условно программиста, заказчика и пользователя. Разумеется дается какое-то ТЗ. Хорошо что бы ТЗ было проработано, но как правило,результат надо корректировать. Кнопки не те задействованы, не такая последовательность в меню настройки, хотелось бы добавить еще и это и это. Вот это и есть сопровождение программы. И этим должен заниматься программист уже после того как программа прошла тестирование, бета-тестирование. Но если заказчик сразу забъет на планирование работы, думая что "опытный" программист вывезет, и проект в свободном "пролете". Может пусть проект "пролетает" и дальше.
Мой вариант воспользоваться классом джойстик Полный скетч здесь https://yadi.sk/d/x92BFogP3G2iiB
Код главного файла выкладываю
/* Class_do_joystic.ino
#1 джойстик VRx ->A0 (VRx_pin)
VRy ->A1 (VRy_pin)
SW ->A2 (SW_pin)
Принцип кода:Отработать джойстик
*/
//#1 Джойстик
#include "Cl_do_joystic.h"
const byte VRx_pin = A0;
const byte VRy_pin = A1;
const byte SW_pin = A2;
void Do_VRx(void);
void Do_VRy(void);
void Do_SW(void);
Cl_do_joystic Joystic(VRx_pin, VRy_pin, SW_pin, // пины для подключения джойстика
0, // 0 - уровень наж кнопке SW
& Do_VRx, & Do_VRy, & Do_SW); // какую функцию надо сделать
void Do_VRx(void) {
Serial.print("VRx= ");
Serial.println(Joystic.VRx);
}
void Do_VRy(void) {
Serial.print("VRy= ");
Serial.println(Joystic.VRy);
}
void Do_SW(void) {
Serial.println("Press SW");
}
void setup() {
Serial.begin(9600);
//#1 Джойстик
Joystic.setup();
}
void loop() {
//#1 Джойстик
Joystic.loop();
}
Пробовать надо.
Как управлять им по заданным значениям?
Так нужен интерфейс данного мотора с энкодером. А еще надо рисовать полностью класс данного устройства. Надо еще учитывать , что у вас будет парралельно что-то еще работать на этом МK. Я бы немного нарисовал это. Но 1 нужна примерная схема вашего мотора и энкодеров. + кнопки + дисплей. А потом будете спрашивать у других управление через сериал и оболочку кидающющие команды на вашу Дуе.
Так еще подкину скетч для размышлений https://yadi.sk/d/WT0l3qE23AKXKx и головной файл сюда
/* class_do_keys_4х4.ino
* https://yadi.sk/d/WT0l3qE23AKXKx
#1 клавиатура 4x4
строки->2,3,4,5 выхода
колонки->6,7,8,9 входа
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
Принцип кода:При нажатии на соответствующую кнопку выполняется соответсвующее действие
*/
//#1 клавиатура 4x4
#include "Cl_do_keys_4x4.h"
Cl_do_keys_4x4 do_keys_4x4; // создать клавиатуру 4х4
void func_1(void) {
Serial.println("do Func 1");
}
void func_2(void) {
Serial.println("do Func 2");
}
void func_3(void) {
Serial.println("do Func 3");
}
void func_4(void) {
Serial.println("do Func A");
}
void func_5(void) {
Serial.println("do Func 4");
}
void func_6(void) {
Serial.println("do Func 5");
}
void func_7(void) {
Serial.println("do Func 6");
}
void func_8(void) {
Serial.println("do Func B");
}
void func_9(void) {
Serial.println("do Func 7");
}
void func_10(void) {
Serial.println("do Func 8");
}
void func_11(void) {
Serial.println("do Func 9");
}
void func_12(void) {
Serial.println("do Func C");
}
void func_13(void) {
Serial.println("do Func *");
}
void func_14(void) {
Serial.println("do Func 0");
}
void func_15(void) {
Serial.println("do Func #");
}
void func_16(void) {
Serial.println("do Func D");
}
void setup() {
Serial.begin(9600);
//#1 клавиатура 4x4
do_keys_4x4.setup(2, 3, 4, 5, 6, 7, 8, 9);
}
void loop() {
//#1 клавиатура 4x4
do_keys_4x4.loop(& func_1, & func_2, & func_3, & func_4,
& func_5, & func_6, & func_7, & func_8,
& func_9, & func_10, & func_11, & func_12,
& func_13, & func_14, & func_15, & func_16);
}
Вы уверены, что это сервопривод. Может это мотор с энкодером?
Ну тогда все просто. Садишься и пишешь. От простого к сложному. Начиная со схемы программы
/*to_Daniel_S.ino
#1 Енкодер
CLK -> 2
DIR -> 2
#2 Индикатор
#3 Мотор
Вращение +
Вращение -
#4 Конечники
Крнечник -
Конечник +
#5 Кнопки
Кнопка stop
Кнопки +
Кнопка -
*/
// #1 Енкодер
// #2 Индикатор
// #3 Мотор
// #4 Конечники
// #5 Кнопки
void setup() {
// #1 Енкодер
// #2 Индикатор
// #3 Мотор
// #4 Конечники
// #5 Кнопки
}
void loop() {
// #1 Енкодер
// #2 Индикатор
// #3 Мотор
// #4 Конечники
// #5 Кнопки
}
И как вы себе представляете этот процесс. Рабочая программа или нет можно определить только залив в уже готовую машину и запустив. А так дистанционно не имея даже макета станка написать рабочую , можно сказать авантюрно, даже если и не бесплатно.
Пропускал шаги и вращался свободно из за х***го драйвера ШД. Будет мощный драйвер и блок питания и проблемы уйдут.