Библиотека для цифрового выхода

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

Arhat109-2 пишет:

чьи-то помои

Чтобы узнать чьи помои, достаточно нажать Ctrl+F и поискать по странице слово "говно". Первый раз оно встречается в Вашем посте №21До этого в топике шла нормальначя беседа. Но тут Вы "тоже решил поучаствовать" и полилось говно рекой. Так что, насчёт "чьих-то помев" Вы не скромничайте, прямо указывайте автороство.

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

yul-i-an пишет:

ЕвгенийП, я так понимаю необходимо использовать перегрузку оператора "=".

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

Давайте.

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

Если будете реализовывать и другие операторы (сравнение, там или ещё чего), там прежде чем делать, посмотрите что такое friends. Иногда оператор гораздо удобнее реализовывать не членом класса, а "другом".

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

yul-i-an пишет:

Arduino позволяет пользователю сосредоточиться на разработке проектов, а не изучении устройства и принципов функционирования отдельных элементов.

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

ГЛАВНЫМ приемуществом среды Arduino, я считаю открытость системных обращений к регистрам и возможность постепенного ухода от всяких analogread() и переход на прямую работу с контроллером.

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

Бросьте эту разработку. В Ардуинке и так мало памяти и мощности, и заворачивать медленные стандартные функции в дополнительные процедуры и классы я не вижу смысла.

Видимо вы еще не столкнулись с проблемой когда все работет медленно и упрощать больше нечего.

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

Okmor пишет:

Бросьте эту разработку. В Ардуинке и так мало памяти и мощности, и заворачивать медленные стандартные функции в дополнительные процедуры и классы я не вижу смысла.

Ну, есть же и другой путь? Добавить всё, что хочется и как нужно, а потом просто заменить обращения к функциям на прямую работу с портами, если так хочется. Чем это плохо?

Logik
Offline
Зарегистрирован: 05.08.2014

Okmor пишет:

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

ГЛАВНЫМ приемуществом среды Arduino, я считаю открытость системных обращений к регистрам и возможность постепенного ухода от всяких analogread() и переход на прямую работу с контроллером.

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

Бросьте эту разработку. В Ардуинке и так мало памяти и мощности, и заворачивать медленные стандартные функции в дополнительные процедуры и классы я не вижу смысла.

Видимо вы еще не столкнулись с проблемой когда все работет медленно и упрощать больше нечего.

+1. Читаеш такое и понимаеш - есть же ещё здоровые люди на форуме, только редко пишут. 

Дополню только, что переход в "в поля прямой работы", совсем не "ушел и не вернулся". Это возможность реализации на том уровне, на котором конкретно в данном случае удобно и требуется, надо ввод с АЦП быстро по прерыванию  - не проблема, а не требуется именно здесь и сейчас - ну и analogRead сойдет. Широта выбора вариантов реализации сохраняется, как бы глубоко в железяку не залазил. 

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Okmor пишет:

Бросьте эту разработку. В Ардуинке и так мало памяти и мощности, и заворачивать медленные стандартные функции в дополнительные процедуры и классы я не вижу смысла.

Видимо вы еще не столкнулись с проблемой когда все работет медленно и упрощать больше нечего.

В #18 посте писал

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

На форуме кроме осцилографа и генератора сигналов мало кому скорость нужна.

Вот когда самонаводящиеся ракеты будим строить тогда и копнем:) , а пока что есть. Никому не навязываю.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

добавил blink(интервал, импульс) - интервал в ms, импульс в ms (продолжительность импульса не дольше интервала). По умолчанию период 1000, импульс 250. Работу loop() не прерывает.

DigOut.h

#ifndef DigOut_h
#define DigOut_h
//#include <arduino.h>
class DigOut
{
  public:
  DigOut(int pin=13, bool state=0);
	void HI();//установить высокий уровень
    void LO();//установить низкий уровень
	void invert();//инвертировать выход
	bool state();//получить состояние
	void blink(unsigned long period=1000, int impuls=250);//выдает импульсы с заданным периодом и длиной
//	void HIafter(unsigned long period=0);//выставить высокий уровень через
//	void LOafter(unsigned long period=0);//выставить низкий уровень через
 	void ResT();//сброс таймера
 private:
    int _pin;//выходной пин
	unsigned long preMillis;//предыдущее время
	bool st;//флаг таймера
};
 
#endif

DigOut.cpp

#include <arduino.h>	
#include "DigOut.h"

DigOut::DigOut(int pin, bool state)
{
  _pin = pin;
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, state);
  preMillis=millis();
}
 
void DigOut::HI()//установить высокий уровень
{
  digitalWrite(_pin, HIGH);
}
 
void DigOut::LO()//установить низкий уровень
{
  digitalWrite(_pin, LOW);
}

bool DigOut::state()//получить состояние выхода
{
  return digitalRead(_pin);
}

void DigOut::invert()//инвертировать выход
{
  digitalWrite(_pin, !digitalRead(_pin));
}

void DigOut::blink (unsigned long period, int impuls)//выдавать импульсы
{
	  if (millis()-preMillis>=period){//если интервал прошел
	  preMillis=millis();//сбрасываем
	  }
	  if(millis()<impuls+preMillis){//если время свечения индикатора не прошло
	    HI();
	  }
	  else//иначе
	  {
	    LO();
	  }
}

Пример

//Пример Blink с использованием библиотеки DigOut
#include <DigOut.h>//подключаем библиотеку
DigOut LED(13);//инициализация цифрового выхода 13 с установкой низкого уровня

void setup() {  
}

void loop() {
LED.blink(1000,300);//мигаем с интервалом 1сек, вспышка 300мс
}

DigOut библитоека

Logik
Offline
Зарегистрирован: 05.08.2014

yul-i-an пишет:

На форуме кроме осцилографа и генератора сигналов мало кому скорость нужна.

Вот когда самонаводящиеся ракеты будим строить тогда и копнем:) , а пока что есть. Никому не навязываю.

Как же Вы неправы в своем утверждении!!! Просто ссылки на темы недавние мелькавшие - 

http://arduino.ru/forum/obshchii/skorost-raboty-displeev (один этот момент чего стоит!!!)

http://arduino.ru/forum/programmirovanie/bystroe-chtenie-tsifrovykh-vkho...

http://arduino.ru/forum/programmirovanie/kak-povysit-skorost-chteniya-sd...

http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-a...

Это за минуту, шо вспомнил, шо нашел.  Еще гдето бодание про I2C на 800КГц было..

Мало того один из кючевых моментов правильного кода - быстрый loop, от чего с delay воюем. И если на всякую фигню (а ввод/вывод согласитесь не сложное дело) тратить много времени то как тут быть?

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

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

Титановый велосипед для кнопки тоже написан на "Ардуиновских" функциях и никто не возмущается, даже в шапку подшили.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну .. в шапке много разного бреда. Может для того и подшили чтобы "так не делали", нет? :) Ну и с классом титановой кнопки там как-бы все нормально и особо лишнего нет. В отличии от этих классов. Я ещё могу понять, если Вы хотите вывести в дальнейшем их работу через прямое указание портов и битов, минуя Wiring, но как-то шибко сомнительно. В противном случае, ваши классы - это яркий пример "как не надо делать".

Logik
Offline
Зарегистрирован: 05.08.2014

yul-i-an пишет:

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

Титановый велосипед для кнопки тоже написан на "Ардуиновских" функциях и никто не возмущается, даже в шапку подшили.

Ну для кнопки,  при разумном подходе, скорость действительно не главное. Если её опрашивать пару десятков раз в секунду, то какая разница как. Вобще где нет проблемы- не надо её выдумывать

ПС. От класса кнопки я тоже не в восторге. ИМХО он не нужен, надуман, но многие начинают разработку именно с кнопки, как будто у них важней устройств нет, потому его существование не вызывает острого неприятия, пусть дети поиграются;)

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

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

ПС. От класса кнопки я тоже не в восторге.

ну, ты бы сказал мне в теме класса, от чего ты не в восторге.

Logik пишет:

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

ну, установи в классе static const byte bounce_            =   0; // длительность отслеживания дребезга.

и, будет тебе твоё персональное счастье.

Logik
Offline
Зарегистрирован: 05.08.2014

У меня и так счастье. Огромное и всеобемлющее без класса кнопки. Не в восторге от подхода. Класс экрана - понимаю зачем, класс сервопривода - тоже, класс кнопки - не понимаю зачем, но допускаю, пусть детки побалуются (если в проекте только кнопка и светодиод, то и кнопка это Девайс с большой буквы))), класс пина - штука ненужная и вредная. 

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Не в восторге от подхода.

хуиз "подход"?

Logik пишет:

класс кнопки - не понимаю зачем

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

Logik
Offline
Зарегистрирован: 05.08.2014

Та ужеж писал, нет никакого обработчика))) Кнопка ростом не вышла для такого громкого звания)) Это и есть подход. У Вас класс системного времени есть в приложении? Нет. И вызова millis с головой хватает.  Или класс светодиода на 13-м пине. Нет. Дижиталврайт13 и усьо;)) Так и класс кнопки - он не нужен. "Скрипач - не нужен". 

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Та ужеж писал, нет никакого обработчика))) 

ок. назови горшком и опубликуй код - я не сильно буду смеяться.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Arhat109-2 пишет:

Ну .. в шапке много разного бреда. Может для того и подшили чтобы "так не делали", нет? :) Ну и с классом титановой кнопки там как-бы все нормально и особо лишнего нет. В отличии от этих классов. Я ещё могу понять, если Вы хотите вывести в дальнейшем их работу через прямое указание портов и битов, минуя Wiring, но как-то шибко сомнительно. В противном случае, ваши классы - это яркий пример "как не надо делать".

В тему анекдот.

Аспирант в открытом вольере научно-исследовательского института проводит опыт со своей человекообразной обезьяной. Показывает обезьяне банан, а потом вешает его на высокую ветку. Обезьяна подходит и начинает трясти дерево. Ветка ходит ходуном, но банан не падает.
Аспирант:
- Думай, Марта, думай!! !
Обезьяна крутит головой, находит палку и сбивает ею банан.
- Молодец Марта.
Аспирант вешает новый банан, уводит обезьяну отдыхать. Когда он возващется с новой обезьяной, то видит, что в вольер проник прапорщик и отчаянно трясет дерево, стараясь достать банан. Аспирант уже собрался выгнать его, но решил понаблюдать за ним. Через некоторое время он не выдерживает и говорит:
- Бери палку прапорщик!!! !
прапор (злобно)
- На хр...на мне палка!! ! Мне банан нужен!!!!

Так вот. Кому палка не нужна пусть и дальше трясут)

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

Та ужеж писал, нет никакого обработчика))) 

ок. назови горшком и опубликуй код - я не сильно буду смеяться.

Отчего же не повеселить.. вот собственно весь ввод с 3-х кнопок.. Последние 4 строки - отладка на экран, остальные 8 строк - все. Какой нафиг класс..

  void loop(
....

  KBD=0;
  if(Time-TimeKBD>300)
  {
      byte kbd=  digitalRead(KBD_K1)+2*digitalRead(KBD_K2)+4*digitalRead(KBD_K3);
      kbd^=7; //комутируем землю
      if(kbd)
      {
        TimeKBD=Time;
        Sound=PIs; // пищим коротко
        KBD=kbd;   // код нажатиой
      }
       
      myOLED.setFont( SSD1306::FONT_SIZE_1); 
      char s[10];
      ltoa(kbd,s,10);
      myOLED.drawString(0,0,s);
  }
.....

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Я понял только одно, если бы я назвал класс Relay&LEDControl, вопросов к скорости работы невозникло.

И что плохого в том чтобы просто объявить relay(10) и управлять им relay.HI(), relay.LO(), relay.blink(1000,500)

Тут многие пишут int relay=10?:( digitalWrite(relay,HIGH) - это нормально номер пина в переменные вносить?

 

Logik
Offline
Зарегистрирован: 05.08.2014

 

yul-i-an пишет:

Я понял только одно, если бы я назвал класс Relay&LEDControl, вопросов к скорости работы невозникло.

Только класс Relay. Как для оччень тормознутых устройств ;) Но вопрос "а нафига" останется.

 

yul-i-an пишет:

 - это нормально номер пина в переменные вносить?

 

Нет

Logik пишет:

 Абстрагировать пины можна только на уровень выше, соблюдая принцип адресация пина (порта, маски и т.д.) константой. 

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Какой нафиг класс..

красавчик, чо... свалить всё в одну кучу, что бы затем разгребать результат.

нажатие на одну кнопку на заданное время отрубает остальные, затем перебираешь все возможные комбинации нажатий, что бы понять, что вообще произошло - сколько и какие кнопки были нажаты?

ок. а, для 10 кнопок, так же будешь поступать? сколько комбинаций вариантов нажатий будешь перебирать?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Logik пишет:

Только класс Relay. Как для оччень тормознутых устройств ;) Но вопрос "а нафига" останется.

Смотрите первый пост темы.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Автор, вам уже не один я отписал, что Вы пишете лисапед. Мало того, что это лисапед, так ещё и 5-и колесный, и с квадратными колесами. Не, мазохизм тоже имеет место быть в жизни .. я вовсе не против. Но позиционировать мазохизм как религию и предлагать всем (библиотека) - увольте. :)

По вашей аналогии с классом Relay.. да хоть горшком назови, он от этого "ногодрыгом" быть не перестанет! Про что вам уже Logik и отписал: "а нафига?" (лисапед 5-и колесный, да-да, он самый!).

Да, и то как Вы прописали пин в виде константы - это нормальная практика программирования МК. Абстрагирование от чиселки константой препроцессора. Каждая ного МК исполняет и ПРЕДНАЗНАЧЕНА (что важно!) ровно для решения своей задачи... и "абстрагировать" далее .. банально нечего. Все попытки писать "универсальные" (5-и колесные) лисапеды - от глупости и непонимания зачем ваще нужны микроконтроллеры. Ну .. или привычка кодить там, где никто не спросит ни за объем памяти ни за скорость исполнения .. то есть за качество решения. "работает и ладно".

P.S. Офигел вчера: поставил Убунту с Юнити на 4-й пенек и обнаружил скорость ввода с клавиатуры .. 1 клавиша в 3(ТРИ!) секунды .. ладно, я понимаю что графика слабовата, рисует медленно и печально .. но чтобы ввод склавы решался задержками типа delay как у мелкософта было в свое время .. не, такого представить себе в среде линуксоидов не мог.. пипец какой-то.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Arhat109-2 пишет:

P.S. Офигел вчера: поставил Убунту с Юнити на 4-й пенек и обнаружил скорость ввода с клавиатуры .. 1 клавиша в 3(ТРИ!) секунды ..

бросай, всё что всем обещал сделать вчера и начинай переписывать клавиатуру для Линукса сейчас - хватит это терпеть!

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

красавчик, чо... свалить всё в одну кучу, что бы затем разгребать результат.

if(KBD&1)  //нажали -поехали Это проблема? 

Клапауций 232 пишет:

нажатие на одну кнопку на заданное время отрубает остальные, затем перебираешь все возможные комбинации нажатий, что бы понять, что вообще произошло - сколько и какие кнопки были нажаты?

ок. а, для 10 кнопок, так же будешь поступать? сколько комбинаций вариантов нажатий будешь перебирать?

Клапауций 232 пишет:

нажатие на одну кнопку на заданное время отрубает остальные, затем перебираешь все возможные комбинации нажатий, что бы понять, что вообще произошло - сколько и какие кнопки были нажаты?

Какие нафиг комбинации? В проекти не предусмотрены. Это банальная навигация: лево, право и ОК.

А даже если нужно, так и тоже пожалуста -  if(KBD&(1|2) )  //нажали комбинацию 1 и 2  -поехали 

Только надо с таймаутом подшаманить нажмут не совсем одновременно,  я в курсе;) 

Клапауций 232 пишет:

ок. а, для 10 кнопок, так же будешь поступать? сколько комбинаций вариантов нажатий будешь перебирать?

Если честно - ХЗ. Будет задача, будем посмотреть. Но в таком подходе 10 не пугает. Вот 33 настораживает. Про комбинации писал - любые и скокохош.

Битовые операции - сила ;)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

А нафиг? Поставил последний Дебиан и всё, делов-то. Даже кеды бегают вполне прилично. :)

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Какие нафиг комбинации?

внезапно, да?

Logik пишет:

Только надо с таймаутом подшаманить нажмут не совсем одновременно,  я в курсе;) 

ага. подшамань - допиши: даблклик, удержание, отслеживание неактивности.

напиши велосипед без класса.

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

Какие нафиг комбинации?

внезапно, да?

Цитаты приводятся с завершенным содержанием. Там так:"Какие нафиг комбинации? В проекти не предусмотрены. "

А то из твоего сам знаеш чего можно надергать...

Клапауций 232 пишет:

 

Logik пишет:

Только надо с таймаутом подшаманить нажмут не совсем одновременно,  я в курсе;) 

ага. подшамань - допиши: даблклик, удержание, отслеживание неактивности.

напиши велосипед без класса.

Так не в первое. К примеру есть у меня тут девайсик где все управление на енкодере, там кнопочка ух как завернута.

Но по реализации я так понял больше вопросов нет. На хрена класс кнопки если решается в 8 строк 3 кнопки?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

На хрена класс кнопки если решается в 8 строк 3 кнопки?

нахрена 8 строк, если всё решается одной строкой if(digitalRead(pin)) {}; ?

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

На хрена класс кнопки если решается в 8 строк 3 кнопки?

нахрена 8 строк, если всё решается одной строкой if(digitalRead(pin)) {}; ?

Ух-ты!! сразу 3 кнопки 8))). 

Ну елы палы! Покажи всем шо я не прав в реализации! Дафай код на своем кллассе делающий тоже самое что и мой, т.е. почти нифига. Дальше ржом вместе, считаем размер по флешу и ОЗУ, число строк (или букв) в исходнике ;).. Короче развлекаемся по полной,  а то шото скучно здесь последние 48 часов ))) 

Кстати класс экрана в 8 строк переписать не выходит. Я пробовал. Никак. Потому там класс имеет смысл.

ПС. Можем в веловетку переместится.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Ух-ты!! сразу 3 кнопки 8))). 

ну, ок - 3 строки. по любому мой вариант лучше. :D

Logik пишет:

Ну елы палы! Покажи всем шо я не прав в реализации!

я же тебе указал, что всё, что ты сделал для сокращения размера кода - не реализовал ничего, кроме if(Time-TimeKBD>300) считая результат Time-TimeKBD общим для всех кнопок.

плюс ты породил некую сущность KBD , которая вызовет у тебя для примера из 10 кнопок 99 ифов для разгребания результата.

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

*можно спорить с тобой бесконечно, но битовые операции - это же круто, да? а, класс экрана что-то там.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

ЕвгенийП, не получается переопределить оператор "=".

	DigOut operator=(DigOut& right) {
        if (this == &right) {
            return *this;
        }
        DigOut.state = &right.value;
        return *this;
    }

В чем может быть проблемма?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

ПС. Можем в веловетку переместится.

нет - там достаточно гениального бреда. 

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

Ух-ты!! сразу 3 кнопки 8))). 

ну, ок - 3 строки. по любому мой вариант лучше. :D

Действительно, так лучше чем три обекта класса кнопки а в каждом ;)

 

boolean click_down;
boolean click_up;
boolean doubleclick;
boolean timer;
boolean retention;
//=================================
unsigned long m;
boolean  p;
boolean  b;
boolean dc;
byte     c;
boolean  t;
boolean  r;

Клапауций 232 пишет:

я же тебе указал, что всё, что ты сделал для сокращения размера кода - не реализовал ничего, кроме if(Time-TimeKBD>300) считая результат Time-TimeKBD общим для всех кнопок.

Ну да. ну да. А про это ОЗУ, та хрени с теми 15 байтами на кнопку. На фоне таблицы виртуальных методов не так и много ;))) 

Клапауций 232 пишет:

плюс ты породил некую сущность KBD , 

byte KBD; ???))) Ну ладно сущность - так сущность.

Клапауций 232 пишет:

которая вызовет у тебя для примера из 10 кнопок 99 ифов для разгребания результата.

нее... если их реально много то свич или косвенный переход, или мапируется на события если такая модель есть в проекте (мапируются - это не map() это как правило "+").  Под настроение и ситуацию. 

 


Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Действительно, так лучше чем три обекта класса кнопки а в каждом ;)

boolean click_down;
boolean click_up;
boolean doubleclick;
boolean timer;
boolean retention;
//=================================
unsigned long m;
boolean  p;
boolean  b;
boolean dc;
byte     c;
boolean  t;
boolean  r;

ок.

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

*простой булевый вопрос. да/нет?

далее... сколько строк в этом коде?

void read() {
unsigned long nm =      millis();
boolean       np = digitalRead(_pb);
boolean nb  = 0;
click_down  = 0;
if (np != p) {p = np; m = nm;}
if (nm - m > bounce_     ) {nb  = 1;}
if (nb  != b ) {b  = nb ;
if (p  == 0 && b == 0) {click_down  = 1;}
}
}

як нэвдобно выйшло... но библиотека индикатора что-то там, правда?

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

Logik пишет:

 класс для int ожидать. 

Делается и очень часто. Например, когда нужно постоянно диапазон значений контролировать

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

yul-i-an пишет:

ЕвгенийП, не получается переопределить оператор "=".

	DigOut operator=(DigOut& right) {
        if (this == &right) {
            return *this;
        }
        DigOut.state = &right.value;
        return *this;
    }

В чем может быть проблемма?

Теперь уж завтра

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Переписал класс. Скорость функций HI(), LO() по сравнению со стандартым digitalWrite выросла примерно в 1,45 раза. Написан конечно криво, надо подумать как изящней переписать (избавится от switch).

DigOut.h

#ifndef DigOut_h
#define DigOut_h
//#include <arduino.h>
class DigOut
{
  public:
  DigOut(int pin=13, bool state=0);
	void HI();//установить высокий уровень
        void LO();//установить низкий уровень
	void invert();//инвертировать выход
	bool state();//получить состояние
	void blink(unsigned long period=1000, int impuls=250);//выдает импульсы с заданным периодом и длиной

 private:
    int _pin;//выходной пин
	unsigned long preMillis;//предыдущее время
};
 
#endif

DigOut.cpp

#include <arduino.h>	
#include "DigOut.h"

DigOut::DigOut(int pin, bool state)//конструктор
{
  _pin = pin;
  pinMode(_pin, OUTPUT);
  if (state==0){LO();}
  else {HI();}
  preMillis=millis();
}
 
void DigOut::HI()//установить высокий уровень
{
   	     switch (_pin) {
		 case 0:
           PORTD |= (1 << 0);//HI
          break;
		 case 1:
           PORTD |= (1 << 1);//HI
          break;
		 case 2:
           PORTD |= (1 << 2);//HI
          break;
		 case 3:
           PORTD |= (1 << 3);//HI
          break;
		 case 4:
           PORTD |= (1 << 4);//HI
          break;
		 case 5:
           PORTD |= (1 << 5);//HI
          break;
		 case 6:
           PORTD |= (1 << 6);//HI
          break;
		 case 7:
           PORTD |= (1 << 7);//HI
          break;
		 case 8:
           PORTB |= (1 << 0);//HI
          break;
		 case 9:
           PORTB |= (1 << 1);//HI
          break;
	      case 10:
           PORTB |= (1 << 2);//HI
          break;
		 case 11:
           PORTB |= (1 << 3);//HI
          break;
		 case 12:
           PORTB |= (1 << 4);//HI
          break;
		 case 13:
           PORTB |= (1 << 5);//HI
          break;
		 }
}
 
void DigOut::LO()//установить низкий уровень
{
    	     switch (_pin) {
		 case 0:
           PORTD &= ~((1 << 0));//LO
          break;
		 case 1:
           PORTD &= ~((1 << 1));//LO
          break;
		 case 2:
           PORTD &= ~( (1 << 2));//LO
          break;
		 case 3:
           PORTD &= ~((1 << 3));//LO
          break;
		 case 4:
           PORTD &= ~((1 << 4));//LO
          break;
		 case 5:
           PORTD &= ~((1 << 5));//LO
          break;
		 case 6:
           PORTD &= ~((1 << 6));//LO
          break;
		 case 7:
           PORTD &= ~((1 << 7));//LO
          break;
		 case 8:
           PORTB &= ~((1 << 0));//LO
          break;
		 case 9:
           PORTB &= ~((1 << 1));//LO
          break;
	      case 10:
           PORTB &= ~((1 << 2));//LO
          break;
		 case 11:
           PORTB &= ~((1 << 3));//LO
          break;
		 case 12:
           PORTB &= ~((1 << 4));//LO
          break;
		 case 13:
           PORTB &= ~((1 << 5));//LO
          break;
		 }
 }

bool DigOut::state()//получить состояние выхода
{
  return digitalRead(_pin);
}

void DigOut::invert()//инвертировать выход
{
  digitalWrite(_pin, !digitalRead(_pin));
}

void DigOut::blink (unsigned long period, int impuls)//выдавать импульсы
{
	  if (millis()-preMillis>=period){//если интервал прошел
	  preMillis=millis();//сбрасываем
	  }
	  if(millis()<impuls+preMillis){//если время свечения индикатора не прошло
	    HI();
	  }
	  else//иначе
	  {
	    LO();
	  }
}

DigOut.rar

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

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

*простой булевый вопрос. да/нет?

Нет канешно! False тоесть ;) Хай меня покрасят, шоб я реализовывать функционал какогото самопального класса.. Я ж четко писал.

Logik пишет:

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

Код работает, замечаний нет. Ты попросил показать, поржать хотел, я показал. А реализовывать класс титановый велосипед.... Ты наверно шутиш, да? Мне это в программе нафиг надо.

Вот еще полюбопытствовал я на счет реализации ровно того же что и у меня через твой класс. Ты стыдливо отвернулся. Я глянул в класс и обомлел - 15 байт ОЗУ на 1 кнопку!!! Нах, нах,нах...

Клапауций 232 пишет:

 

як нэвдобно выйшло... но библиотека индикатора что-то там, правда?

Невдобно конечно, но я ж понимаю, ты весь на нервах, бум щитать от ненависти ;)

А чего это за код был?  и чего снова для одной кнопки? Хотя после 15байт на один пин уже и не важно...

Вывод. Замена существующего кода в моем приложении на реализацию на основе класса титанового велосипеда потребует значительного количества доп. ресурсов контроллера. Усьо! 

ПС. О пользе диалога. Призадумался, чего это я комбинации кнопок проигнорил. Конечно 3-х кнопок хватает, но на дополнительные 4 комбинации можна тоже чего навесить. В общем на днях допишу себе таки ввод комбинаций, спасибо  Клапауций 232. Если кого интересует, пишите выложу здесь.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Вот еще полюбопытствовал я на счет реализации ровно того же что и у меня через твой класс. Ты стыдливо отвернулся. Я глянул в класс и обомлел - 15 байт ОЗУ на 1 кнопку!!! Нах, нах,нах...

я же тебе дал код. ок - дублирую

void read() {
unsigned long nm =      millis();
boolean       np = digitalRead(_pb);
boolean nb  = 0;
click_down  = 0;
if (np != p) {p = np; m = nm;}
if (nm - m > bounce_     ) {nb  = 1;}
if (nb  != b ) {b  = nb ;
if (p  == 0 && b == 0) {click_down  = 1;}
}
}

Logik пишет:

А чего это за код был?  

не знаю, а ты как думаешь, чего это код?

Logik пишет:

и чего снова для одной кнопки? Хотя после 15байт на один пин уже и не важно...

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

но, это же костыль - я не понимаю, зачем ты это делаешь... что бы было много свободной оперативки, что бы что?

*проверил класс с урезанным функционалом для 10-ти кнопок - 89 байт (4%) ок. для 100 кнопок займёт 40% оперативки. а, ты как будешь рулить 100 кнопками и со свободной оперативкой? придумаешь новую отмазку или поймёшь, что ты написал костыль?

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

yul-i-an пишет:

ЕвгенийП, не получается переопределить оператор "=".

	DigOut operator=(DigOut& right) {
        if (this == &right) {
            return *this;
        }
        DigOut.state = &right.value;
        return *this;
    }

В чем может быть проблемма?

А так:

DigOut& operator=(const DigOut& right) 
{
        if (this == &right) 
        {
            return *this;
        }
         this->state = right.state;
        return *this;
 }

Принцип в том, что сперва проверяешь, что присваивание вызывается не для одного и того же объекта. Потом копируешь поля из переданного объекта себе, поле к полю, а не так, как ты сделал (DigOut.state = right.value) - шо такое right.value?

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

yul-i-an, потом настанет черёд конструктора копирования ;) А потом, до кучи - explicit-конструктора, чтобы исключить неявные преобразования. Потом - можно определить операторы сравнения, операторы типов  - например, operator int(), который будет возвращать номер пина, чтобы можно было удобно писать

DigOut ledPin(13);

int pin = ledPin; // в pin - число 13

И ещё куча разных вкусных плюшек, например:

DigOut ledPin(13);

ledPin << true; // включим пин

ledPin << false; // выключим пин

тоже решается оператором ;) Кури, С++ вкусный язык.

З.Ы. Ну а потом дойдём и до шаблонов когда-нибудь :)

З.З.Ы. Конечно, рулить пинами с помощью класса - избыточно, но мы ведь не этого добиваемся? Смотри, насколько интересная конструкция:

DigOut pinManager;

pinManager << 13 << true; // выставили HIGH на пине 13

pinManager << 22 << false; // выставили LOW на пине 22

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

В общем, считаю, что экономить надо начинать тогда, когда совсем уже жмёт, так что - тренируйся, перейти на низкий уровень никогда не поздно.

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

Вот еще полюбопытствовал я на счет реализации ровно того же что и у меня через твой класс. Ты стыдливо отвернулся. Я глянул в класс и обомлел - 15 байт ОЗУ на 1 кнопку!!! Нах, нах,нах...

я же тебе дал код. ок - дублирую

....

Logik пишет:

А чего это за код был?  

не знаю, а ты как думаешь, чего это код?

И ты не знаеш... А нафига запостил?  Я про свой код думаю, мне  хватает..

Клапауций 232 пишет:

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

Неправильно понимаеш.

Клапауций 232 пишет:

но, это же костыль - я не понимаю, зачем ты это делаешь... что бы было много свободной оперативки, что бы что?

 Это сложно, у меня их просто нет. Смотри код, найдеш-покажеш.

Клапауций 232 пишет:

*проверил класс с урезанным функционалом для 10-ти кнопок - 89 байт (4%) ок. для 100 кнопок займёт 40% оперативки. а, ты как будешь рулить 100 кнопками и со свободной оперативкой? придумаешь новую отмазку или поймёшь, что ты написал костыль?

10 или 100 или мульен. А что делать если встречу динозавра... Детский сад. 

Еще раз с начала. У меня кнопки, их 3 шт. Ровно 3 кнопки запомнил. Во вторых у меня код есть, без левых классов и работает. Ты утверждаеш что если перейти на твой велосипед то будет как минимум не хуже. Так? Подтверди да или нет.

 Я же вижу что как минимум ОЗУ уйдет дохера, а это хуже. Вижу по классу. Ты суеш какую-то функцию, сам не знаеш что и зачем,  но она похоже для одной кнопки (которая уже ОЗУ отгребает как мои 3 кнопки), расказываеш про 10 или 100.  Ты посотри на ту функцию, ввод digitalRead(_pb); и _pb глобальная. Как мне это использовать для 3-х кнопок? Три  функции делать шоле.  Каким боком она вобще к твоему классу относится? Фигня какая-то неопознаная. Расказы "мог бы, слил бы" - в топку, есть опубликованый класс, но он не тянет. Я выбор сделал, выводы написал. 

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

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Logik пишет:

Кста кода, обрабатывающего одновременное нажатие нескольких в классе не видно шото.

а, должен быть в классе код, обрабатывающий несколько, а не одну кнопку?

ок. вот тебе ещё(в третий) раз код класса, урезанный до твоего функционал(нажатие кнопки) - копипасть на здоровье. :D

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// класс титановый велосипед для тактовой кнопки.
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.

#include <Arduino.h>

class BUTTON {
public:
//===============================================================================================
static const byte bounce_            =   50; // длительность отслеживания дребезга.
// static const byte doubleclick_       =  200; // длительность отслеживания двойного клика.
// static const unsigned long timer_    = 5000; // длительность отслеживания неактивности.
// static const unsigned int retention_ = 2000; // длительность отслеживания нажатия и удержания.
//===============================================================================================
boolean click_down;
// boolean click_up;
// boolean doubleclick;
// boolean timer;
// boolean retention;
//=================================
unsigned long m;
boolean  p;
boolean  b;
// boolean dc;
// byte     c;
// boolean  t;
// boolean  r;
//=================================
byte _pb;
//=================================
BUTTON(byte pb) {
_pb = pb;
pinMode(_pb, INPUT);
digitalWrite(_pb, 1);
//====
click_down  = 0;
// click_up    = 0;
// doubleclick = 0;
// timer       = 0;
// retention   = 0;
//====
m  =      millis();
p  = digitalRead(_pb);
b  =          0;
// dc =          0;
// c  =          0;
// t  =          0;
// r  =          0;
//====
}

void read() {
//=======================================================
unsigned long nm =      millis();
boolean       np = digitalRead(_pb);
//=================
boolean nb  = 0;
// boolean ndc = 0;
// boolean nt  = 0;
// boolean nr  = 0;
//================
click_down  = 0;
// click_up    = 0;
// doubleclick = 0;
// timer       = 0;
// retention   = 0;
//=================
if (np != p) {p = np; m = nm;}
//=======================================================
if (nm - m > bounce_     ) {nb  = 1;}
// if (nm - m > doubleclick_) {ndc = 1;}
// if (ndc != dc) {dc = ndc;
// if (dc == 1) {c = 0;}
// }
if (nb  != b ) {b  = nb ;
if (p  == 0 && b == 0) {click_down  = 1;
            // ++c;
// if (c  == 2) {c = 0;    doubleclick = 1;}
}
// if (p  == 1 && b == 1) {click_up    = 1;}
}
//=======================================================
// if (nm - m > timer_      ) {nt  = 1;}
// if (nt  != t ) {t  = nt ;
// if (p  == 1 && t == 1) {timer       = 1;}
// }
//=======================================================
// if (nm - m > retention_  ) {nr  = 1;}
// if (nr  != r ) {r  = nr ;
// if (p  == 0 && r == 1) {retention   = 1;}
// }
//=======================================================
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

скетч-тест 10 кнопок - обработка нажатия.


// #include <class_BUTTON.h>
#include <class_BUTTON_mini.h>

BUTTON BUTTON_01( 3);
BUTTON BUTTON_02( 4);
BUTTON BUTTON_03( 5);
BUTTON BUTTON_04( 6);
BUTTON BUTTON_05( 7);
BUTTON BUTTON_06( 8);
BUTTON BUTTON_07( 9);
BUTTON BUTTON_08(10);
BUTTON BUTTON_09(11);
BUTTON BUTTON_10(12);

void setup() {
pinMode(14, OUTPUT);
digitalWrite(14, 1);
}

void loop() {

BUTTON_01.read();
BUTTON_02.read();
BUTTON_03.read();
BUTTON_04.read();
BUTTON_05.read();
BUTTON_06.read();
BUTTON_07.read();
BUTTON_08.read();
BUTTON_09.read();
BUTTON_10.read();

if (BUTTON_01.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_02.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_03.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_04.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_05.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_06.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_07.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_08.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_09.click_down) {digitalWrite(14, !digitalRead(14));}
if (BUTTON_10.click_down) {digitalWrite(14, !digitalRead(14));}

}

Logik пишет:

Ты утверждаеш что если перейти на твой велосипед то будет как минимум не хуже. Так? Подтверди да или нет.

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

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

сделал выбор и сделал - ходи на трёх ногах, но нафига хаять, то чему у небя неприязнь на эмоциональном уровне.

Logik пишет:

Ты посотри на ту функцию, ввод digitalRead(_pb); и _pb глобальная. Как мне это использовать для 3-х кнопок? 

варианта два:
1. убиться ап стену.
2. зайти в нужную тему и посмотреть как.
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Переписал класс. Скорость функций HI(), LO() по сравнению со стандартым digitalWrite выросла примерно в 1,45 раза. Написан конечно криво, надо подумать как изящней переписать (избавится от switch).

Давайте пока не будем этим заниматься. Всему своё время.

Я понимаю, что Вас смущают замечания прогеров насчёт эффективности, но во-первых, таким способом Вы от этих замечаний не избавитесь, т.к. всё равно есть пути сделать это эффективнее, а во-вторых, я же Вам говорил, если Вы хотите научиться, то давайте идти шаг за шагом и, в какой-то момент, мы просто заменим методы HI/LO на самые эффективные, а вся, сделанная нами, оснастка останется нетронутой.

Заменить методы можно в любой момент, это очень просто. Некоторые тут не знают как это делается. но скачали где-то пример в котором не сумели разобраться. Поэтому им это кажется сложным (всё, в чём не сумел разобраться, кажется сложным), на самом деле, ничего там сложного нет, если знать и правильно применять язык.

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

начнём с оператор априсваивания. Коллега DIYMan всё правильно написал, но я хочу пойти дальше. Но, для начала, давайте зафиксируем текст класса (а то я уже запутался в Ваших версиях). Я сейчас выложу текст с которым я буду работать и давайте пока мы не закончим с низкоуровневой оснасткой, мы не будем добавлять туда высокоуровневые методы типа blink.

Итак, текст класса:

#ifndef DigOut_h
#define DigOut_h

#include <arduino.h>

class DigOut {
public:
	// Конструктор
	DigOut (const int8_t pin=13, const bool state=0) {
		pinMode(_pin = pin, OUTPUT);
		(state) ? HI() : LO();
	}

	//	установить уровень
	void DW(const bool state) const {
		digitalWrite(_pin, state);
	}

	// установить высокий уровень
	void HI(void) const {
		DW(HIGH);
	}

	// установить низкий уровень
	void LO() const {
		DW(LOW);
	}

	// инвертировать выход
	void invert(void) const {
		DW(!state());
	}

	// получить состояние
	bool state(void) const {
		return digitalRead(_pin);
	}

private:
	int8_t _pin;	//выходной пин
};
 
#endif

Текст проверчного примера:

#include "DigOut.h"

void setup(void) {}

void loop(void) {
	static DigOut p13;
	delay(500);
	p13.invert();
}

Вроде, всё мигает. давайте, будем плясать строго от этого текста, чтобы мы говорили об одном и том же.

Кстати, обратите внимание, что я сократил тип данных _pin (зачем ему два байта занимать?) и всем методам добавил модификатор const, чтобы развязать руки оптимизатору.

Теперь вернёмся к присваиванию. Для начала сделаем присваивание экземпляро класс друг другу.

иВаши ошибка в том, что 

1) Вы возвращаете экземпляр класса, а надо ссылку
2) у Вас нет свойста, которое хранит состояние. Состояние хранится непосредственно на самом пине, так? Ну, так значит при присваивании оно должно получить значение! А Вы этого не сделали.
3) при присваивании Вы проверяете, а не самому ли себе идёт присваивание. В общем случае это хорошая практика, но в данном случае это лишнее - зачем? Какая разница? Вы же не запрашиваете память и не делаете ничего страшного.

Таким образом, алгоритм присваивания одного экземпляра другому таков:

1. Установить состояние текущего экземпляра класса таким же каково состояние присваиваемого.
2) вернуть ссылку на текущий экземпляр.

Так и пишем: 

DigOut & operator = (DigOut & original) {
	DW(original.state()); // присвоили состояние
	return *this;	// вернули ссылку
}

Вот и всё.

Текущий текст класса:

#ifndef DigOut_h
#define DigOut_h

#include <arduino.h>

class DigOut {
public:
	// Конструктор
	DigOut (const int8_t pin=13, const bool state=0) {
		pinMode(_pin = pin, OUTPUT);
		(state) ? HI() : LO();
	}

	//	установить уровень
	void DW(const bool state) const {
		digitalWrite(_pin, state);
	}

	// установить высокий уровень
	void HI(void) const {
		DW(HIGH);
	}

	// установить низкий уровень
	void LO() const {
		DW(LOW);
	}

	// инвертировать выход
	void invert(void) const {
		DW(!state());
	}

	// получить состояние
	bool state(void) const {
		return digitalRead(_pin);
	}

	DigOut & operator = (DigOut & original) {
		DW(original.state()); // присвоили состояние
		return *this;	// вернули ссылку
	}

private:
	int8_t _pin;	//выходной пин
};
 
#endif

Текст проверочного примера

#include "DigOut.h"

void setup(void) {}

void loop(void) {
	static DigOut p13, p7(7);
	delay(500);
	p7.invert();
	p13 = p7;
}

Всё понятно? Если непонятно, спрашивайте.

Теперь определим присваивание экземпляру класса значение типа bool, чтобы можно было писать "p13 = LOW" вместо вызова функции.

Итак, сложного ничего нет, по традиции оператор присваивания должен вернуть присвоенное значение, значит тип у него bool. Нужно просто выставить значение. Техника такова, смотрите:

bool operator = (const bool newState) {
	DW(newState);
	return newState;
}

Текущий текст класса:

#ifndef DigOut_h
#define DigOut_h

#include <arduino.h>

class DigOut {
public:
	// Конструктор
	DigOut (const int8_t pin=13, const bool state=0) {
		pinMode(_pin = pin, OUTPUT);
		(state) ? HI() : LO();
	}

	//	установить уровень
	void DW(const bool state) const {
		digitalWrite(_pin, state);
	}

	// установить высокий уровень
	void HI(void) const {
		DW(HIGH);
	}

	// установить низкий уровень
	void LO() const {
		DW(LOW);
	}

	// инвертировать выход
	void invert(void) const {
		DW(!state());
	}

	// получить состояние
	bool state(void) const {
		return digitalRead(_pin);
	}

	// Присваивание одного экземпляра другому
	DigOut & operator = (DigOut & original) {
		DW(original.state()); // присвоили состояние
		return *this;	// вернули ссылку
	}

	// Присваивание экземпляру значение типа bool
	bool operator = (const bool newState) {
		DW(newState);
		return newState;
	}

private:
	int8_t _pin;	//выходной пин
};
 
#endif

Текст проверочного примера

#include "DigOut.h"

void setup(void) {}

void loop(void) {
	static bool ledOn = false;
	static DigOut p13;
	delay(500);
	ledOn = (p13 = ! ledOn);
	
}

Понятно?

Теперь, прежде, чем мы перейдём дальше, домашнее задание.

1) проверьте, работает ли наше присваивание типа bool в случае, если попытаться присвоить тип int;

2) попробуйте сами реализовать преобразование к типу bool. Чтобы можно было писать вместо "bool isOn = p13.state();" просто  "bool isOn = p13;"

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

Евгений, хочу заметить, что это не совсем верный подход, кмк, т.к. цепочка вызовов разрушается:

bool operator = (const bool newState) {
	DW(newState);
	return newState;
}

Надо:

DigOut& operator = (const bool newState) {
	DW(newState);
	return *this;
}

Плюс определить оператор bool:

DigOut::operator bool()
{
 return currentState;
}

Тогда будут работать и цепочки вызовов, например:

DigOut d1, d2;
bool b;
d1 = b = d2 = true;

И получение состояния в переменную типа bool:

bool b = d2;

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

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

DIYMan пишет:

Евгений, хочу заметить, что это не совсем верный подход, кмк, т.к. цепочка вызовов разрушается:

bool operator = (const bool newState) {
	DW(newState);
	return newState;
}

Надо:

DigOut& operator = (const bool newState) {
	DW(newState);
	return *this;
}

Нет, нет, Вы перепутали. Это присваивание значение типа bool (посмотрите на параметр оператора!).

Любой оператор присваивания должен возвращать то, что было присвоено. Не новое значение экземпляра объекта, а именно то, что было присвоено. Разумеется, это не жёсткое требование, на практике мы можем вернуть что угодно, но такое соглашение есть и я ему следовал. Поэтому данный оператор должен возвращать именно bool! Цепочка же будет отлично работать, если определить преобразование типа этого класса к bool. Тогда можно писать конструкции вроде p13 = p12 = p7 = true;

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

 

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

Евгений, безусловно, я понимаю, о чём вы:

Цитата:

  • All built-in assignment operators return *this, and most user-defined overloads also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void).

Однако:

Цитата:

the canonical "unified assignment operator" implementation is

T& T::operator=(T arg) // copy/move constructor is called to construct arg
{
    swap(arg); // resources are exchanged between *this and arg
    return *this;
} // destructor of arg is called to release the resources formerly held by *this

И я всегда придерживаюсь второго подхода, возвращая *this, т.к. мы работаем с объектом класса, который может быть и lvalue. Считаю, что оперировать объектом класса в перегруженных операторах - это самое грамотное поведение, вне зависимости от того, какой объект нам передали в оператор (в нашем случае оператор присваивания). Скажем, если мы переопределим оператор <<, то там, очевидно, надо всегда возвращать *this, вне зависимости от переданного аргумента, не находите?

T& T::operator<<(int val)
{
cout << val; return *this;
}
T& T::operator<<(const String& s)
{
cout << s.c_str(); return *this;
}

T t;

t << 123 << "Hello, " << 456 << ", world!";

В приведённом примере противопоказано возвращать что-либо, отличное от ссылки на объект ;)

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

DIYMan пишет:

В приведённом примере противопоказано возвращать что-либо, отличное от ссылки на объект ;)

Ну, в приведённом-то само собой :)))

Да, нет, ну, понятно, что вопрос идеологический и можно делать как угодно. Важно только определиться и в пределах всего проекта делать одинаково, чтобы бардака не было. Если ТС захочет возвращать *this - да не вопрос, ему-то сейчас глваное просто научиться возвращать то, что хочет :) Опять же, если в добавок к возвращению *this будет определено преобразование к bool, то и цепочное присваивание bool'евским переменным будет отлично работать, так что можно делать и так - никаких проблем.

Я тут, как видите. всё вынес в inline и готовлю ТС, чтобы в нужный момент просто заменить вызовы digitalXXX (методы HI/LO) на портовые команды так, чтобы все операции сразу однокомандными стали, а то ведь прогеры ему печень съедят, если будет не так :)

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 232 пишет:

Logik пишет:

Кста кода, обрабатывающего одновременное нажатие нескольких в классе не видно шото.

а, должен быть в классе код, обрабатывающий несколько, а не одну кнопку?

Так ты же сам про комбинации кнопок заговорил! )))) А оказывается нет, небыло и не должно.

Клапауций 232 пишет:

ок. вот тебе ещё(в третий) раз код класса, урезанный до твоего функционал...

 Себе оставь, я ж те четко написал. Эту хрень я не использовал, не буду и другим не рекомендую. Почему - разжевано выше. Можеш урезать, зарезать, отрезать, прирезать. И шо это за подход к либе - урезал и пользуй.  Под каждого будеш урезать? А тестить буш сам?. Кстати после урезания он тоже жрет больше ОЗУ. Может обрезание надо, шоб кошерный был? DDD

 

Logik пишет:
Ты утверждаеш что если перейти на твой велосипед то будет как минимум не хуже. Так? Подтверди да или нет.

Клапауций 232 пишет:

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

 Ну понятно, неудобные вопросы игнорируеш.

Клапауций 232 пишет:

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

 Та то ты их слышать нехош. 15 байт ОЗУ на кнопку - это приговор. После этого код просто не рассматривается как вариант.

Клапауций 232 пишет:
 то чему у небя неприязнь на эмоциональном уровне.
 

 Чешеш хрень. Я даже попробовал прикинуть переход на твой класс. И сравнил оба варианта, класс проиграла сразу и бесповоротно, по ОЗУ. Что и подтверждает исходное - для кнопки класс не нужен. До сравнения вариантов по остальным пунктам дело не дошло. Потому класса  -небудет!

Logik пишет:
Ты посотри на ту функцию, ввод digitalRead(_pb); и _pb глобальная. Как мне это использовать для 3-х кнопок? 

Клапауций 232 пишет:
 

варианта два:
1. убиться ап стену.
2. зайти в нужную тему и посмотреть как.

 

Ответа по существу нет. ну и нахер, вопрос про класс решен.

ПС. От интересно, Клапауций, ты действительно считаеш, что я закоментирую  свой код (который короче экономней твоего по ОЗУ и работает замечательно, к тому же легко модифицировался под прием нескольких одновременных нажатий) и всуну твой "урезок" (который длинней, жрет больше ОЗУ и токошо тобой поправлен и нихрена ни  тещен и соответственно нихрена не надежен)? И токо из за того шо ты написал "костыль" да "три ноги", без каких либо аргументов. Пиши еще!!   При этом еще и автор на вопросы не отвечает и претензии игнорит . Можеш на это не отвечать, вопрос риторический..