Да нет, когда поймёт пусть private применяет. А по умолчанию всегда protected.
Захочет он лет через 5 потомков от своего сегодняшнего класса породить и «хапнет». Уж лучше сразу такое вызубрить.
Да нет, когда поймёт пусть private применяет. А по умолчанию всегда protected.
Захочет он лет через 5 потомков от своего сегодняшнего класса породить и «хапнет». Уж лучше сразу такое вызубрить.
и он прав.
Это банально не будет работать на многих контроллерах
я бы его назвал init()
Что касается пинов - вам зачем надо, чтобы они были недоступны? Чтобы юзер их не изменил? - ну так сделайте их константами
Сейчас попробую.
Мельком глянул исходник.
Споткнулся на строках 29-56.
if(arrow){
uk = (uk - 1) & 3;
} else {
uk = (uk + 1) & 3;
}
а если пожертвовать наглядностью:
uk = (uk + 1 - 2*arrow) & 3;
protected не использую, пока не хапнул. А если хапну - кто помешает мне свой класс подправить? ))
Тогда он не сможет их назначать, будет привязан к заданным
в момент создания экземпляра - сможет.
А то что после их уже не поменять - так на то они и константы.
Спасибо за намек. Но я пока с этим не разобрался, поэтому для начала остановился на этом:
if (arrow==true) uk=(uk+3) % 4;
else uk=(uk+1) % 4;
Но вот так тоже работает
uk = (uk + 2 * arrow + 1) % 4;
Изменить константу? Хм…
не изменить, а инициализировать:
class MOTORS
{
private:
const int pin11;
const int pin22;
const int pin33;
const int pin44;
public:
MOTORS(const int pin1, const int pin2, const int pin3, const int pin4):
pin11(pin1), pin22(pin2), pin33(pin3), pin44(pin4)
{
}
void init() {
pinMode(pin11, OUTPUT);
pinMode(pin22, OUTPUT);
pinMode(pin33, OUTPUT);
pinMode(pin44, OUTPUT);
}
};
MOTORS m(2,3,4,5);
void setup() {
m.init();
}
void loop() { }
Разобрался с Вашим #24. Красиво! Два младших бита в uk показвают отстаток от деления на 4. Он то и нужен. Но перед этим смещаете uk и глушите биты 2-7.
В конструкторе пины и прописывать, тогда при инициализации класса они и будут назначаться на выход, а потом переключаться в ф-х класса.
Можно будет подключить еще двигатели на другие пины, инициировав еще экземпляр класса с другими пинами. Вроде так.
Да я ж не против.
Просто я стараюсь читать, что пишет Евгений Петрович, а ты видимо нет.
Ну или еще какая причина, не знаю. На гитхабе в серьезных проектах private практически не встретить…
Чой-та нет? Нигде Петрович о вреде private не писал
Ну как это не писал? Писал…
Я вот найти только не могу, может быть он сам сегодня заглянет и прояснит (вдруг я чего-то не понял? Нельзя исключать…).
Писал о пользе protected, а не о вреде private ))
ЗЫ: если ты точно уверен, что никогда не будешь наследовать этот класс, или наследники обойдутся без приватных методов/полей, то какой смысл?
Вот, я никогда в этом не уверен )))
ЗЫ: Ничего о вреде private я тоже не писал.
А я вот уверен, что бывают случаи, когда приватные поля/методы нужно скрывать даже от потомков класса ))
Ну, это я удачно паузу взял. Вам практически всё уже написали.
(все номера строк по самому первому скетчу)
private
, я тоже считаю его здесь чрезмерным. С задачей недоступности из программы вполне и protected
справится. А использование private
сужает возможности дальнейшего использования класса, а именно – запрещает классам-наследникам доступ к этим переменным;То нет особого смысла делать его классом.
Ну, теперь, что я ещё заметил по мелочи (“крупняк” пока оставим):
moment2
(а в строке №29 – uk
, а в строке №80 – arrow2
) используются до инициализации. Нет, я понимаю, что Вы используете то, что изначально они нули, но это некрасивая практика – коробит аж. Неужели трудно поставить инициализацию?pin1
, pin2
, pin3
и т.п. надо бить по рукам. У этих пинов есть вполне осмысленные функции и переменные заслуживают осмысленных названий;mkstep
(как и появившейся позже begin
) не изменяет никаких свойств класса. И не собирается изменять! Тогда почему он (метод) не объявлен const
? Просто, в силу упомянутого выше правила?uk
и выводом на пины, нуждается в серьёзно сутевом комментарии.Теперь про “крупняк”. (я согласен со всем, что написали коллеги, но здесь буду использовать Ваш изначальный код без правок, которые они предложили. Эти правки Вы сами внесёте).
Если в классе все методы inline
, как у Вас, то нет никакого смысла иметь константные свойства – они только память отжирают. Все константные свойства можно и нужно вынести в параметры шаблона. Смотрите:
class MOTORS
{
private:
int pin11, pin22, pin33, pin44;
public:
MOTORS(int pin1, int pin2, int pin3, int pin4)
{
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
pin11 = pin1;
pin22 = pin2;
pin33 = pin3;
pin44 = pin4;
}
void mkstep(bool arrow)
{
static unsigned long moment2;
while (millis() - moment2 < 2)
{
}
moment2 = millis();
static byte array1[] = {1, 0, 0, 1};
static byte array2[] = {1, 1, 0, 0};
static byte array3[] = {0, 1, 1, 0};
static byte array4[] = {0, 0, 1, 1};
static byte uk;
digitalWrite(pin11, array1[uk]);
digitalWrite(pin22, array2[uk]);
digitalWrite(pin33, array3[uk]);
digitalWrite(pin44, array4[uk]);
if (arrow == true)
{
switch (uk)
{
case 0: uk = 3;
break;
case 1: uk = 0;
break;
case 2: uk = 1;
break;
case 3: uk = 2;
break;
}
}
else
{
switch (uk)
{
case 0: uk = 1;
break;
case 1: uk = 2;
break;
case 2: uk = 3;
break;
case 3: uk = 0;
break;
}
}
}
};
// подключение шагового двигателя
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
MOTORS Stmt(IN1, IN2, IN3, IN4);
byte arrow2;
void setup()
{
}
void loop()
{
Stmt.mkstep(arrow2);
}
У меня показывает память программы/данных: 1092/38
А вот
template <const uint8_t pin1, const uint8_t pin2, const uint8_t pin3, const uint8_t pin4>
class MOTORS
{
public:
MOTORS(void)
{
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
}
void mkstep(bool arrow)
{
static unsigned long moment2;
while (millis() - moment2 < 2)
{
}
moment2 = millis();
static byte array1[] = {1, 0, 0, 1};
static byte array2[] = {1, 1, 0, 0};
static byte array3[] = {0, 1, 1, 0};
static byte array4[] = {0, 0, 1, 1};
static byte uk;
digitalWrite(pin1, array1[uk]);
digitalWrite(pin2, array2[uk]);
digitalWrite(pin3, array3[uk]);
digitalWrite(pin4, array4[uk]);
if (arrow == true)
{
switch (uk)
{
case 0: uk = 3;
break;
case 1: uk = 0;
break;
case 2: uk = 1;
break;
case 3: uk = 2;
break;
}
}
else
{
switch (uk)
{
case 0: uk = 1;
break;
case 1: uk = 2;
break;
case 2: uk = 3;
break;
case 3: uk = 0;
break;
}
}
}
};
// подключение шагового двигателя
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
MOTORS<IN1, IN2, IN3, IN4> Stmt;
byte arrow2;
void setup()
{
}
void loop()
{
Stmt.mkstep(arrow2);
}
У меня показывает память программы/данных: 1038/30
Как видите, мы сэкономили и то, и другое.
Конечно, это правило (как и любое другое) надо применять с умом.
(это уже не про класс, правда)
Зачем они память жрут? Давайте посмотрим на строки №№29-32. В них Вы всегда двум пинам выставляете HIGH
и двум пинам – LOW
. При этом, в зависимости от uk
имеем:
uk | pin1 | pin2 | pin3 | pin4 |
---|---|---|---|---|
0 | 1 | 1 | 0 | 0 |
1 | 0 | 1 | 1 | 0 |
2 | 0 | 0 | 1 | 1 |
3 | 1 | 0 | 0 | 1 |
Легко заметить, что:
pin1
получает значение HIGH
при uk
== 0 или 3
pin2
– при uk
< 2
pin3
– при uk
== 1 или 2
pin4
– при uk
> 1
Ну, и кто нам мешает так и написать в строках №№29-32
digitalWrite(pin11, uk==0 || uk==3);
digitalWrite(pin22, uk < 2);
digitalWrite(pin33, uk==1 || uk==2);
digitalWrite(pin44, uk > 1);
И массивы не нужны вовсе.
Это при Ваших значениях uk
. А если бы Вы сделали их такими, чтобы просто за каждый пин отвечал свой бит в uk
, было бы ещё проще.
Вот! Я же говорю - недавно было…
чтобы просто за каждый пин отвечал свой бит в
uk
Я не представляю как это сделать. Поэтому реализовал с битовыми операциями так (здесь я решил перейти на 8-ми тактовый режим).
Переменную uk
переименовал в takt
.
void mkstep(bool arrow)
{
static unsigned long moment2;
while (millis() - moment2 < 1)
{
}
moment2 = millis();
static byte takt;
takt = (takt + 2 * arrow - 1) & 7;
// такт (takt)
// 0 1 2 3 4 5 6 7
// 0 0 0 0 0 1 1 1
// 0 0 0 1 1 1 0 0
// 0 1 1 1 0 0 0 0
// 1 1 0 0 0 0 0 1
digitalWrite(pin11, bitRead(0b00000111, takt));
digitalWrite(pin22, bitRead(0b00011100, takt));
digitalWrite(pin33, bitRead(0b01110000, takt));
digitalWrite(pin44, bitRead(0b11000001, takt));
}