Вы хотели сказать "14"? А то уж скоро стандарт 17 выйдет.
Да и это тоже. Вот только туговато у меня получается с теорией как писать программы на Си++, с применением ООП ,Абстрактного класса и Абстракного типа данных. Это как электрический ток . Вроде все ясно, но в все равно окончательного ответа не получается.
Приветствую,можно ли привести пример простенькой программки для nano ,чтобы светодиод моргал сначала 1 раз,потом 2,3 и так далее до бесконечности.Заранее -Спасибо.
решение через delay
/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
//-------main()----------------------------
void setup() {
pinMode(pin, OUTPUT);
for (int n = 1;; ++n) {
for (int i = 0; i < n; ++i) {
digitalWrite(pin, HIGH);
delay(/*время вкл*/200);
digitalWrite(pin, LOW);
delay(/*время выкл*/200);
}
delay(/*пауза между сериями*/500);
}
}
void loop() {
}
/*Скетч использует 968 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/
Промежуточная разметка
/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
//-------main()----------------------------
void setup() {
pinMode(pin, OUTPUT);
for (int n = 1;; ++n) {
for (int i = 0; i < n; ++i) { // stat =0
digitalWrite(pin, HIGH); // stat =1
delay(/*время вкл*/200); // stat =2
digitalWrite(pin, LOW);
delay(/*время выкл*/200); // stat =3
} // stat =4
delay(/*пауза между сериями*/500); // stat =5
}
}
void loop() {
}
/*Скетч использует 968 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/
Ну и перевод в millis()
/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
int stat = 0, n = 1, i;
uint32_t mill, past;
//-------main()----------------------------
void setup() {
pinMode(pin, OUTPUT);
}
void loop() {
mill = millis();
if (stat == 0) { // 0
stat = 1;
i = 1;
}
if (stat == 1) { // 1
stat = 2;
digitalWrite(pin, HIGH);
past = mill;
}
if (stat == 2 && mill - past >=/*время вкл*/200) { // 2
stat = 3;
digitalWrite(pin, LOW);
past = mill;
}
if (stat == 3 && mill - past >=/*время выкл*/200) { // 3
stat = 4;
digitalWrite(pin, LOW);
past = mill;
}
if (stat == 4) { // 4
if (i < n) {
stat = 1;
++i;
}
else stat = 5;
}
if (stat == 5 && mill - past >=/*пауза между сериями*/500) { // 5
stat = 0;
past = mill;
++n;
}
}
/*Скетч использует 1268 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 23 байт (1%) динамической памяти, оставляя 2025 байт для локальных переменных. Максимум: 2048 байт.
*/
А теперь упакован код в класс
/**/
uint32_t mill;//millis()
//-----------------------------------------------------
class Cl_Led {
const byte pin ;
int stat = 0, n = 1, i;
uint32_t past;
public:
Cl_Led(byte _pin): pin(_pin) {}
void setup() {
pinMode(pin, OUTPUT);
stat = 0;
}
void loop() {
if (stat == 0) { // 0
stat = 1;
i = 1;
}
if (stat == 1) { // 1
stat = 2;
digitalWrite(pin, HIGH);
past = mill;
}
if (stat == 2 && mill - past >=/*время вкл*/200) { // 2
stat = 3;
digitalWrite(pin, LOW);
past = mill;
}
if (stat == 3 && mill - past >=/*время выкл*/200) { // 3
stat = 4;
digitalWrite(pin, LOW);
past = mill;
}
if (stat == 4) { // 4
if (i < n) {
stat = 1;
++i;
}
else stat = 5;
}
if (stat == 5 && mill - past >=/*пауза между сериями*/500) { // 5
stat = 0;
past = mill;
++n;
}
}
};
//-------компоновка----------------------------
Cl_Led Led(/*пин*/13);
//-------main()----------------------------
void setup() {
Led.setup();
}
void loop() {
mill = millis();
Led.loop();
}
/*Скетч использует 1340 байт (4%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 24 байт (1%) динамической памяти, оставляя 2024 байт для локальных переменных. Максимум: 2048 байт.
*/
ПС: Тут скорее появился вопрос: Зачем? delay компактнее. Ответ. delay просто съедает ресурсы производительности процессора. А без этих ресурсов сэкономленая флеш и Озу память бесполезна для будущей модернизации программы.
// а вы уверены что так?
PIND |= (1 << 3);
// а может так
*out ^=bit&inv;
// а то у Метров такие мелочи не волнуют
Вопрос не понятен. Я написал "Например для третьего пина". Так вот, для тертьего пина - это действительно так, я уверен (и даташит тоже). А как Вам это перевести в Ваш класс и сделать универсально для любого пина - это Ваша забота.
Только не забывайте. так как я написал - это ОДНА машинная команда и НОЛЬ байтов дополнительной памяти данных. Вы же зачем-то пытаетесь помнить какую-то переменную и выполнять логику с нею. Зачем? Для инвертирования пина, как я Вам писал, достаточно записать 1 в нужный бит PINx (и неважно. что там было раньше - запишете единицу ещё раз - инвертируется ещё раз). Попробуйте.
/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
volatile uint8_t *reg; // указатель на регистр настройки порта
volatile uint8_t *out; // указатель на регистр входа порта
bool inv;// состояние бита инверсии выхода
bool stat;// 1 мигать / 0 нет
unsigned long past, time;
public:
/*
конструктор Cl_Led
Описание создает класс
Ввод pin: подключение к ноге
inv: бит инвертирования 0 нет / 1 инверсия
Вывод нет
*/
Cl_Led (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin); // получить номер порта
reg = portModeRegister(port);
out = portOutputRegister(port);
}
/*
Функция setup
Описание иницирование класса
Ввод нет
Вывод нет
*/
void setup() {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
if (inv) *out &= ~bit;
else *out |= bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция OFF
Описание выключить светодиод
Ввод нет
Вывод нет
*/
void OFF() {
uint8_t oldSREG = SREG;
cli();
if (inv) *out &= ~bit;
else *out |= bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция ON
Описание включить светодиод
Ввод нет
Вывод нет
*/
void ON() {
uint8_t oldSREG = SREG;
cli();
if (inv) *out |= bit;
else *out &= ~bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция blink
Описание мигать светодиодои
Ввод _time - полупериод мигания
Вывод нет
*/
void blink(unsigned long _time = 500) {
time = _time;
stat = 1;
past = mill;
uint8_t oldSREG = SREG;
cli();
*out ^= bit;
SREG = oldSREG;
}
/*
Функция loop
Описание для нормальной работе разместить в loop программы
Ввод нет
Вывод нет
*/
void loop() {
if (!stat) return;
if (mill - past >= time) {
past = mill;
uint8_t oldSREG = SREG;
cli();
*out ^= bit;
SREG = oldSREG;
}
}
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
volatile uint8_t *reg; // указатель на регистр настройки порта
volatile uint8_t *out; // указатель на регистр выхода порта
uint8_t port; // номер порта на выводе
const byte pin;
void (*Do1)(), (*Do2)();
bool btn, btn_old, btn_new;
bool bounce = 0; // антидребезговый флаг
uint32_t past = 0 ;
public:
/*
конструктор Cl_Btn
Описание создает класс
Ввод pin: подключение к ноге
_Do1: фунция обработчик нажатия кнопки
_Do2: фунция обработчик отжатия кнопки
Вывод нет
*/
Cl_Btn(byte pin, void (*_Do1)(), void (*_Do2)()): Do1(_Do1), Do2(_Do2) {
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin); // получить номер порта
reg = portModeRegister(port);
out = portOutputRegister(port);
}
/*
Функция setup
Описание иницирование класса
Ввод нет
Вывод нет
*/
void setup() {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit; //INPUT
*out |= bit; //PULLUP
SREG = oldSREG;
btn_old = (*portInputRegister(port) & bit) == 0;
}
/*
Функция loop
Описание для нормальной работе разместить в loop программы
Ввод нет
Вывод нет
*/
void loop() {
btn_new = (*portInputRegister(port) & bit) == 0;
if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
bounce = 1; // выставить флаг
past = mill; // сделать временую засветку
}
else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
bounce = 0; // то снять флаг
btn_old = btn ;
btn = btn_new ; // прочитать реальное значение на выводе
if (btn_old && ! btn)(*Do1)();
if (!btn_old && btn)(*Do2)();
}
}
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do1_Btn1() {
Led1.ON();
}
void Do2_Btn1() {
Led1.OFF();
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do1_Btn1,/*обраб отж*/Do2_Btn1);
//-------------main()-----------------------------------
void setup() {
Led1.setup();
Btn1.setup();
}
void loop() {
mill = millis();
Led1.loop();
Btn1.loop();
}
/*Скетч использует 1308 байт (4%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 47 байт (2%) динамической памяти, оставляя 2001 байт для локальных переменных. Максимум: 2048 байт.
*/
Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?
Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!
Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?
Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!
Ну компилируется вы же видели это /* */ И работает. Ну да остались рудименты. Так компилятор это и опускает. Умный блин однако, это я про компилятор. const byte pin все же загружаемая переменная, но только с конструктора.
ПС: хотя да без нее на один байт в программе меньше.
/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
volatile uint8_t *reg; // указатель на регистр настройки порта
volatile uint8_t *out; // указатель на регистр входа порта
bool inv;// состояние бита инверсии выхода
bool stat;// 1 мигать / 0 нет
unsigned long past, time;
public:
/*
конструктор Cl_Led
Описание создает класс
Ввод pin: подключение к ноге
inv: бит инвертирования 0 нет / 1 инверсия
Вывод нет
*/
Cl_Led (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin); // получить номер порта
reg = portModeRegister(port);
out = portOutputRegister(port);
}
/*
Функция setup
Описание иницирование класса
Ввод нет
Вывод нет
*/
void setup() {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
if (inv) *out &= ~bit;
else *out |= bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция OFF
Описание выключить светодиод
Ввод нет
Вывод нет
*/
void OFF() {
uint8_t oldSREG = SREG;
cli();
if (inv) *out &= ~bit;
else *out |= bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция ON
Описание включить светодиод
Ввод нет
Вывод нет
*/
void ON() {
uint8_t oldSREG = SREG;
cli();
if (inv) *out |= bit;
else *out &= ~bit;
SREG = oldSREG;
stat = 0;
}
/*
Функция blink
Описание мигать светодиодои
Ввод _time - полупериод мигания
Вывод нет
*/
void blink(unsigned long _time = 500) {
time = _time;
stat = 1;
past = mill;
uint8_t oldSREG = SREG;
cli();
*out ^= bit;
SREG = oldSREG;
}
/*
Функция loop
Описание для нормальной работе разместить в loop программы
Ввод нет
Вывод нет
*/
void loop() {
if (!stat) return;
if (mill - past >= time) {
past = mill;
uint8_t oldSREG = SREG;
cli();
*out ^= bit;
SREG = oldSREG;
}
}
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
volatile uint8_t *reg; // указатель на регистр настройки порта
volatile uint8_t *out; // указатель на регистр выхода порта
uint8_t port; // номер порта на выводе
void (*Do1)(), (*Do2)();
bool btn, btn_old, btn_new;
bool bounce = 0; // антидребезговый флаг
uint32_t past = 0 ;
public:
/*
конструктор Cl_Btn
Описание создает класс
Ввод pin: подключение к ноге
_Do1: фунция обработчик нажатия кнопки
_Do2: фунция обработчик отжатия кнопки
Вывод нет
*/
Cl_Btn(byte pin, void (*_Do1)(), void (*_Do2)()): Do1(_Do1), Do2(_Do2) {
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin); // получить номер порта
reg = portModeRegister(port);
out = portOutputRegister(port);
}
/*
Функция setup
Описание иницирование класса
Ввод нет
Вывод нет
*/
void setup() {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit; //INPUT
*out |= bit; //PULLUP
SREG = oldSREG;
btn_old = (*portInputRegister(port) & bit) == 0;
}
/*
Функция loop
Описание для нормальной работе разместить в loop программы
Ввод нет
Вывод нет
*/
void loop() {
btn_new = (*portInputRegister(port) & bit) == 0;
if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
bounce = 1; // выставить флаг
past = mill; // сделать временую засветку
}
else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
bounce = 0; // то снять флаг
btn_old = btn ;
btn = btn_new ; // прочитать реальное значение на выводе
if (btn_old && ! btn)(*Do1)();
if (!btn_old && btn)(*Do2)();
}
}
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do1_Btn1() {
Led1.ON();
}
void Do2_Btn1() {
Led1.OFF();
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do1_Btn1,/*обраб отж*/Do2_Btn1);
//-------------main()-----------------------------------
void setup() {
Led1.setup();
Btn1.setup();
}
void loop() {
mill = millis();
Led1.loop();
Btn1.loop();
}
/*Скетч использует 1308 байт (4%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 46 байт (2%) динамической памяти, оставляя 2002 байт для локальных переменных. Максимум: 2048 байт.
*/
Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.
1.8.1 - выдаёт не ошибку, но предупреждение (в отличие от 1.6.5 и 1.6.12 - те выдают ошибку - опции разные)
Вот предупреждение 1.8.1
C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino: In constructor 'Cl_Btn::Cl_Btn(byte, void (*)(), void (*)())':
C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino:122:5: warning: uninitialized const member in 'const byte {aka const unsigned char}' [-fpermissive]
C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino:108:16: note: 'const byte Cl_Btn::pin' should be initialized
-------------------
Вы же понимаете, что неинициализировать константу неправильно? Так исправьте, чего спорить-то, проще же просто исправить ошибку чем докуазывать недоказуемое.
Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.
Не в том дело кто может менять, а кто - нет.
Если в классе объявлена константа, конструктор обязан её инициализировать. Вы этого не сделали, вот и ругается.
Если в классе объявлена константа, конструктор обязан её инициализировать. Вы этого не сделали, вот и ругается.
Ну зеванул. Точнее мне захотелось посмотреть код где убран pinMode(),digitalWrite(),digitalRead(). Точнее их раскрыл уже внутри класса. Затем убрал лишние куски, что бы не мешались. Но мой компилятор не предупредил, хотя программа загрузилась и работала. Значит все нормально. Вот даже переменая pin - нога не понадобилась. И да если компилятор чистит код, то глобальные переменые оставляет. Даже если это глобально внутри класса. Этого не знал.
Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.
ну, так и попробуй изменить...
class Cl_AAA {
public:
const byte aaa;//<--- нормально так работает
Cl_AAA(byte _aaa): aaa(_aaa) {}
};
Cl_AAA AAA(/*константа*/1);
void setup() {
AAA.aaa = 5;
}
void loop() {}
sketch_aug13a:8: error: assignment of read-only member 'Cl_AAA::aaa'
AAA.aaa = 5;
/**/
//------qwString---------------------------
//класс стринг
class qwString {
char *buffer;
unsigned len;// длина строки боз последнего \0
/*функция destroy
описание очистить кучу
ввод нет
вывод нет
*/
void destroy() {
if (buffer)
delete[] buffer;
}
public:
/*конструктор qwString
описание конструктор по умолчанию
ввод *data:строка
вывод нет
*/
qwString (): len(0) {
buffer = new char;
buffer[len] = 0;
}
/*конструктор qwString
описание конструктор копирования
ввод data:строка
вывод нет
*/
qwString (qwString & obj) {
len = obj.len;
buffer = new char[len + 1];
strcpy(buffer, obj.buffer);
buffer[len] = 0;
}
/*конструктор qwString
описание перенести данные во вновь создаваемый объект
ввод &&tmp:другой компонент
вывод нет
*/
qwString(qwString&& tmp)
: len(tmp.len), buffer(tmp.buffer) {
tmp.buffer = NULL;
}
/*конструктор qwString
описание создать класс со строкой в 1 символ
ввод data:строка
вывод нет
*/
qwString (char data) {
len = 1;
buffer = new char[2];
buffer[0] = data;
buffer[len] = 0;
}
/*конструктор qwString
описание создать класс со значением строки
ввод *data:строка
вывод нет
*/
qwString (char *data) {
len = strlen(data);
buffer = new char[len + 1];
strcpy(buffer, data);
buffer[len] = 0;
}
/*функция operator=
описание организовать присвоение
ввод other:другой компонент
вывод нет
*/
qwString& operator=(const qwString& other) {
destroy();
len = other.len;
buffer = new char[len + 1];
strcpy(buffer, other.buffer);
buffer[len] = 0;
return *this;
}
/*функция operator=
описание организовать присвоение c переносом
ввод &&tmp:другой компонент
вывод нет
*/
qwString& operator=(qwString&& tmp) {
destroy();
len = tmp.len;
buffer = tmp.buffer;
tmp.buffer = NULL;
return *this;
}
/*деструктор qwString
описание удалить класс
ввод нет
вывод нет
*/
~qwString () {
destroy();
}
/*функция viev
описание показать значение
ввод нет
вывод нет
*/
void viev() {
Serial.print(len);
Serial.print(" ");
Serial.print(buffer);
Serial.println();
}
};
/*функция для проверки перехвата конечного результата функции*/
qwString Create(char *const data) {
qwString _data(data);
return _data;
}
//-------Компоновка----------------------------
//------main()----------------------
void setup() {
Serial.begin(9600);
qwString AAA1 = Create("123"); // срабатывает конструктор перемещения
AAA1.viev();
qwString AAA2 = AAA1; // срабатывает конструктор копирования
AAA2.viev();
AAA2 = Create("456"); // срабатывает конструктор перемещения, затем оператор перемещения
AAA2.viev();
AAA2 = AAA1; // срабатывает оператор присваивания
AAA2.viev();
}
void loop() {
}
/*Скетч использует 2618 байт (8%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 206 байт (10%) динамической памяти, оставляя 1842 байт для локальных переменных. Максимум: 2048 байт.
*/
Строки 73-80 (а также 86-92) - тпипчная ошибка реализации оператора присваивания. При такой реализации присваивание объекта класса самому себе непредсказуемо.
Не всё так просто. Вы используете конструкцию "if(this== &tmp)", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.
Не всё так просто. Вы используете конструкцию "if(this== &tmp)", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.
Разумеется. Там и кроме этого куча ошибок. Но пока не смогу сжевать этот кактус, то о дальнейшем изучении С++ и ОПП говорить бессмысленно.
Этой фразы я не понял. Причём тут Ардуино? То, что разработчики IDE по умолчанию заткнули warning'и, так я Вам уже советовал включить - увидели бы сообщение.
/**/
unsigned long mill;
//------------------------------
const byte led1 =/*пин 1 светодиода*/2;
const byte led2 =/*пин 2 светодиода*/3;
const byte led3 =/*пин 3 светодиода*/4;
void setupLeds() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}
void runLeds(bool stat) {
static unsigned long past;
static byte step;
if (stat) step = 0;
switch (step) {
case 0:
digitalWrite(led1, HIGH);
past = mill;
step = 1;
break;
case 1:
if (mill - past >= 200) { // delay(200);
digitalWrite(led1, LOW);
digitalWrite(led2, HIGH);
past = mill;
step = 2;
}
break;
case 2:
if (mill - past >= 200) { // delay(200);
digitalWrite(led2, LOW);
digitalWrite(led3, HIGH);
past = mill;
step = 3;
}
break;
case 3:
if (mill - past >= 200) { // delay(200);
digitalWrite(led3, LOW);
step = 4;
}
break;
}
}
//----main--------------------------
void setup() {
setupLeds();
runLeds(1);
}
void loop() {
mill = millis();
runLeds(0);
}
/*Скетч использует 1150 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 18 байт (0%) динамической памяти, оставляя 2030 байт для локальных переменных. Максимум: 2048 байт.
*/
Понятно что код непривычен для тех кто мыслит процедурно. Одна и таже процедура(функция) запускается в версии с 1 и в версии с 0. И в setup() и в loop() За то не размазывается по программе как после фугасной бомбы
Ну классов там действительно нету, но ерунды достаточно. И наибольшая в том, что для решения банальнейшего вопроса выдается такой кривой код. А потом удивляемся, почему на форуме простыни кода забитого повторяющимися фрагментами и прочей ерундой. Дак их так учили здесь, примеры такие. Если уж Вы qwone, взялись за неимоверно тяжкую задачу убрать делеи, то предлагайте нормальное решение, а не то за которое будут чмырить позже. Публикуемый код должен быть образцем, а не пробой пера, пробу пера не обязательно людям показывать (за исключением случая когда надо чтоб код оценили и поругали), а тем более советовать как решение. А то ж народ привыкнет так писать.
Смотрю ваш код, нового и оригинального в нем ровно 0. А 3 минуты правки и 2 минуты на тест позволяют преобразовать его, сократив размер скомпилированого на 10%. (с 1300 до 1070 байт) Всего два момента легкой оптимизацией, а структура кода стала более явной, обработчики завершения временных интервалов каждый в своей функции, механизм легко маштабируем и т.д. Так что не публикуйте кривое и сырое, оставте это удовольствие велосипедостроителю ;)
Зачем мне эта грязная простыня? Вы ща как Клапауций, ныть будете "ну глянь, ну попробуй"? Так упреждаю. Я глянул раз, и у него и у Вас. Больше не стоит время терять. Глянул, сделал вывод изложил и даже проилюстрировал. А Ваш уровень писания кода - ваша проблема, плохо что другие на ваш код смотрят и себе так пишут. Хотя и это тоже вобщем не моя проблема ;)
Тема плавно переходит в сборище говнокода от qwone. Но зато наглядно видно что не в классах дело, ох не в классах.
Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной. А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего.
Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной. А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего.
Первый раз открывая тему действительно допускал что чего толковоги и оригинального увижу. Иначе бы и не открывал разумеется. Мой код найти не можете? Странно, его здесь много есть, например из последнего http://arduino.ru/forum/apparatnye-voprosy/dtmf-gsm#comment-302080 . Захотите найти - найдете. Например по работе с модемом А8 большой и оч. интересный код публиковал. Так что упрек не по адресу.
А сырое и кривое точно публиковать не надо, за исключением случая чтоб поругали. Сырого и кривого и на гитхабе теперь валом ;)
Тема выдохлась. И скатилась в замену делея на милис. Напомню только про http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-ch.... Возможно это было бы интересней. И для Вас точно полезней, в ООП продвинулись бы. Например написали бы абстрактный класс реализующий вызов метода через интервалы времени, а на его базе и свой пример последний музыкальный, описав мелодию масивом констант разумеется а не тем бредовым свичем.
Например написали бы абстрактный класс реализующий вызов метода через интервалы времени, а на его базе и свой пример последний музыкальный, описав мелодию масивом констант разумеется а не тем бредовым свичем.
Про астрактный класс (данных или объекта обрабатывающие эти данные )могу сказать одно. Не все что хорошо в теории, хорошо ложится в код. В Гардвадской организации и небольшой памяти точно. Опять я специально привел тот бредовый код , что бы выложить получше сейчас. Ведь пока не видишь разницы думаешь, что есть лучше.
Лучше. Только melody ну никак не массив интов. Массив должен состоять из однотипных величин, а у вас там вперемешку частоты и длительности (тот факт что они инт влезли еще не означает их однотипность). Заведите соответствующую структуру и melody массив структур. Строки 88-91 и 96-98 подозрительно похожи, не так ли? Ну и voidmusic(bytenum) тоже полезно в класс, аналогичный Btn. А если бы они оба наследовали один базовый класс с абстрактным сетапом и лопом то все бы стало еще интересней.
Про архитектуру и как ложится - не переживайте, ляжет. Только напишите ;)
200 кнопок для контроллера?
нет - для суперкомпьютера
Да, у них как-то ваще кнопок негусто - у многих ни одной нет:)
Вот еще задание от сюда http://arduino.ru/forum/programmirovanie/morganie-svetodioda-nuzhnoe-kolichestvo-raz
решение через delay
Промежуточная разметка
Ну и перевод в millis()
А теперь упакован код в класс
ПС: Тут скорее появился вопрос: Зачем? delay компактнее. Ответ. delay просто съедает ресурсы производительности процессора. А без этих ресурсов сэкономленая флеш и Озу память бесполезна для будущей модернизации программы.
Вариант связки классов через статическую переменную и статические функции класса
Вариант связки классов
Каких классов? В скетче, вроде, один всего класс.
Ну можно так
Или так
А можно так
Всем известна программа Blink с delay()
Вот вариант с классом .заменил pinMode и digitalWrite
Ужался код немного.
Добавил в класс инвесию
Странная у Вас инверсия. Для того, чтобы инвертировать пин, достаточно прописать 1 в соответствующий бит регистра PINx.
Например для третьего пина:
и это странслируется в одну единственную машинную команду
Вопрос не понятен. Я написал "Например для третьего пина". Так вот, для тертьего пина - это действительно так, я уверен (и даташит тоже). А как Вам это перевести в Ваш класс и сделать универсально для любого пина - это Ваша забота.
Только не забывайте. так как я написал - это ОДНА машинная команда и НОЛЬ байтов дополнительной памяти данных. Вы же зачем-то пытаетесь помнить какую-то переменную и выполнять логику с нею. Зачем? Для инвертирования пина, как я Вам писал, достаточно записать 1 в нужный бит PINx (и неважно. что там было раньше - запишете единицу ещё раз - инвертируется ещё раз). Попробуйте.
Третий скетч отсюда #109
Получился таким.
Такой же в работе код, но уже на millis()
Код на 3 кнопки и светодиод с миганием на таком же принципе
Последний скетч немного оптимизировал
А эта версия если кнопки или датчики у вас без дребезга
Уроки программирования Ардуино. http://mypractic.ru/uroki-programmirovaniya-arduino-navigaciya-po-urokam
Послушайте, qwone,
Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?
Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!
Послушайте, qwone,
Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?
Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!
Ну компилируется вы же видели это /* */ И работает. Ну да остались рудименты. Так компилятор это и опускает. Умный блин однако, это я про компилятор. const byte pin все же загружаемая переменная, но только с конструктора.
ПС: хотя да без нее на один байт в программе меньше.
qwone, ну реально какой-то поток сознания - нахрена это всё?
Ну компилируется вы же видели это /* */ И работает.
Я вставил в IDE. И ни хрена не компилируется. Как и следовало ожидать выдаёт сообщение
так у меня Ардуино 1.8.0 . Заходит нормально.
Да так смотрю как программа выглядил на форуме с такими комментариями. Всегда найдутся люди со строны и увидят что-то не так.
ок а, тема как называется?
я сюда захожу, что бы научиться чему-то новому.
и, что я вижу - бред сумасшедшего.
да - оно компилится ровно так, как речь шизофреника логически связна, но при длительном наблюдении оказывается бредом.
//<--- нормально так работает
почему не должно работать?
//<--- нормально так работает
почему не должно работать?
так у меня Ардуино 1.8.0 . Заходит нормально.
1.8.1 - выдаёт не ошибку, но предупреждение (в отличие от 1.6.5 и 1.6.12 - те выдают ошибку - опции разные)
Вот предупреждение 1.8.1
Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.
Не в том дело кто может менять, а кто - нет.
Если в классе объявлена константа, конструктор обязан её инициализировать. Вы этого не сделали, вот и ругается.
Ну зеванул. Точнее мне захотелось посмотреть код где убран pinMode(),digitalWrite(),digitalRead(). Точнее их раскрыл уже внутри класса. Затем убрал лишние куски, что бы не мешались. Но мой компилятор не предупредил, хотя программа загрузилась и работала. Значит все нормально. Вот даже переменая pin - нога не понадобилась. И да если компилятор чистит код, то глобальные переменые оставляет. Даже если это глобально внутри класса. Этого не знал.
мой компилятор не предупредил
Посмотрите в настройках IDE "Compiler warnings". По умолчанию "из коробки" там стоит "None". Поставьте "All" - для разработчика это более адекватно.
Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.
ну, так и попробуй изменить...
Код
ПС: как работает не спрашивайте. Вроде понимаю, но похоже не очень твердо.
увековечил в железобетоне #48
Код
Строки 73-80 (а также 86-92) - тпипчная ошибка реализации оператора присваивания. При такой реализации присваивание объекта класса самому себе непредсказуемо.
Класс qwStr строковая переменная(не полная буду наполнять)
Не всё так просто. Вы используете конструкцию "
if
(
this
== &tmp)
", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.Не всё так просто. Вы используете конструкцию "
if
(
this
== &tmp)
", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.Разумеется. Там и кроме этого куча ошибок. Но пока не смогу сжевать этот кактус, то о дальнейшем изучении С++ и ОПП говорить бессмысленно.
Вот еще один вариант класса строковой переменных
Строки 64 и 68 выглядят странно, учитывая, что функция описана как void. Остальное не смотрел.
Строки 64 и 68 выглядят странно, учитывая, что функция описана как void. Остальное не смотрел.
Ну да . В Ардуно вообще код идет такой
Но метод protected: и возвращаемое значение не используется в дальнейшем внутри класса
Ну да . В Ардуно вообще код идет такой
Этой фразы я не понял. Причём тут Ардуино? То, что разработчики IDE по умолчанию заткнули warning'и, так я Вам уже советовал включить - увидели бы сообщение.
Часто идет вопрос : Как заменить delay() на millis(). Две несхожые функции. Это как слона менять на коня. Попробую предложить свой вариант.
Вот есть код.
Ну и результат обмена.
Понятно что код непривычен для тех кто мыслит процедурно. Одна и таже процедура(функция) запускается в версии с 1 и в версии с 0. И в setup() и в loop() За то не размазывается по программе как после фугасной бомбы
Человек просил помощи, а вы ему классы, не занимайтесь ерундой.
Человек просил помощи, а вы ему классы, не занимайтесь ерундой.
Где вы видели там классы.Я ему метод, как решать такие проблемы. причем без классов. Знание методы банально упрощает решение задачи.
Ну классов там действительно нету, но ерунды достаточно. И наибольшая в том, что для решения банальнейшего вопроса выдается такой кривой код. А потом удивляемся, почему на форуме простыни кода забитого повторяющимися фрагментами и прочей ерундой. Дак их так учили здесь, примеры такие. Если уж Вы qwone, взялись за неимоверно тяжкую задачу убрать делеи, то предлагайте нормальное решение, а не то за которое будут чмырить позже. Публикуемый код должен быть образцем, а не пробой пера, пробу пера не обязательно людям показывать (за исключением случая когда надо чтоб код оценили и поругали), а тем более советовать как решение. А то ж народ привыкнет так писать.
Смотрю ваш код, нового и оригинального в нем ровно 0. А 3 минуты правки и 2 минуты на тест позволяют преобразовать его, сократив размер скомпилированого на 10%. (с 1300 до 1070 байт) Всего два момента легкой оптимизацией, а структура кода стала более явной, обработчики завершения временных интервалов каждый в своей функции, механизм легко маштабируем и т.д. Так что не публикуйте кривое и сырое, оставте это удовольствие велосипедостроителю ;)
Logik. Тот скетч я специально не пытался оптимизировать. Я просто показал как переходить с delay на millis хотя бы за счет простыней.
Вот вам еще одна простыня и музакальная пауза одновременно
Зачем мне эта грязная простыня? Вы ща как Клапауций, ныть будете "ну глянь, ну попробуй"? Так упреждаю. Я глянул раз, и у него и у Вас. Больше не стоит время терять. Глянул, сделал вывод изложил и даже проилюстрировал. А Ваш уровень писания кода - ваша проблема, плохо что другие на ваш код смотрят и себе так пишут. Хотя и это тоже вобщем не моя проблема ;)
Тема плавно переходит в сборище говнокода от qwone. Но зато наглядно видно что не в классах дело, ох не в классах.
Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной. А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего.
Вы ща как Клапауций, ныть будете "ну глянь, ну попробуй"? Так упреждаю. Я глянул раз, и у него и у Вас. Больше не стоит время терять.
тогда, иди на йух, упреждатель хренов - напиши библиотеку для кнопки лучше, чем у меня.
делов то.
или, смени ник на Дъартаньян.
Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной. А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего.
Первый раз открывая тему действительно допускал что чего толковоги и оригинального увижу. Иначе бы и не открывал разумеется. Мой код найти не можете? Странно, его здесь много есть, например из последнего http://arduino.ru/forum/apparatnye-voprosy/dtmf-gsm#comment-302080 . Захотите найти - найдете. Например по работе с модемом А8 большой и оч. интересный код публиковал. Так что упрек не по адресу.
А сырое и кривое точно публиковать не надо, за исключением случая чтоб поругали. Сырого и кривого и на гитхабе теперь валом ;)
Тема выдохлась. И скатилась в замену делея на милис. Напомню только про http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-ch.... Возможно это было бы интересней. И для Вас точно полезней, в ООП продвинулись бы. Например написали бы абстрактный класс реализующий вызов метода через интервалы времени, а на его базе и свой пример последний музыкальный, описав мелодию масивом констант разумеется а не тем бредовым свичем.
Про астрактный класс (данных или объекта обрабатывающие эти данные )могу сказать одно. Не все что хорошо в теории, хорошо ложится в код. В Гардвадской организации и небольшой памяти точно. Опять я специально привел тот бредовый код , что бы выложить получше сейчас. Ведь пока не видишь разницы думаешь, что есть лучше.
Лучше. Только melody ну никак не массив интов. Массив должен состоять из однотипных величин, а у вас там вперемешку частоты и длительности (тот факт что они инт влезли еще не означает их однотипность). Заведите соответствующую структуру и melody массив структур. Строки 88-91 и 96-98 подозрительно похожи, не так ли? Ну и
void
music(
byte
num)
тоже полезно в класс, аналогичный Btn. А если бы они оба наследовали один базовый класс с абстрактным сетапом и лопом то все бы стало еще интересней.Про архитектуру и как ложится - не переживайте, ляжет. Только напишите ;)
один базовый класс с абстрактным сетапом и лопом
Про это ТС говорили ещё месяц назад, но, похоже, здесь принципиальное неприятие :)
Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего.
согласен