Поле структуры класс

AsNik
Offline
Зарегистрирован: 24.10.2020

Прошу прощения, может быть вопрос глупый, но я не могу с ним разобраться

есть структура

struct NameStruct {
float f1, f2, f3;
byte b1, b2, b3;
};

и мне в нее(структуру) нужно добавить датчик DHT. На основе этой структуры будет массив

#define COUNT_ARR 3
NameStruct arStruct[COUNT];

Если без этих структур и массивов то датчик объявляется/создается так

#include "DHT.h"

DHT dht(5, DHT22);

Или тут только через указатель делать, типа:

struct NameStruct {
float f1, f2, f3;
byte b1, b2, b3;
char *dht;
};

Но как мне потом его(DHT) туда(в поле dht) засунуть с учетом что нужно их три дуда с разными пинами засунуть?

Ну пины для них будут

byte arPins[COUNT_ARR] = {5, 7, 8};

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

AsNik
Offline
Зарегистрирован: 24.10.2020


Эх, тему создал и пришла сразу такая мысль:
 
for (n=0; n<COUNT_ARR; n++) {
....
DHT arStruct[n].dht(arPins[n], DHT22);
...
}

Правильно ли так? Если почти правильно, то подозреваю, что со * и & у меня проблема. Поправьте если не сложно

Если логически думать, то DHT создаст экземпляр класса - это в принципе и будет указатель. То наверное не нужны эти *&...

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

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

Обычно делается так, в классе определяется указатель на другой класс (DHT в данном случае)

DHT *mDht;

а конструкторе создаем его новый экземпляр

mDht = new DHT(xx,yy);

AsNik
Offline
Зарегистрирован: 24.10.2020

asam пишет:

Если собираешься делать класс

Так в том и дело, что не класс собираюсь делать, а в структуру засунуть экземпляр DHT.

И структура будет в массиве,  поэтому будет несколько экземпляров DHT...

Я вот пока с этим разбираюсь, пришел к такому еще варианту.

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

Но тут есть еще один ньюанс время между считываниями должно быть не менее двух секунд. Это нужно будет учитывать при опросе датчиков... По ходу нарисовалась еще проблема... Но ответ на вопрос как в поле структуры поместить экземпляр объекта интересен.

AsNik
Offline
Зарегистрирован: 24.10.2020

AsNik пишет:

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

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

Задежка реализована в библиотеке, плохо, значит не пойдет данный вариант.

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

AsNik пишет:

 

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

 

Не надо в структуру запихивать экземпляр класса! Это в корне неправильно. Надо туда указатель, а когда создаешь экземпляр класса то его адрес присваешь указателю. Ровно тем же способом что я уже говорил.

AsNik
Offline
Зарегистрирован: 24.10.2020

asam пишет:

Ровно тем же способом что я уже говорил.

#include "DHT.h"


DHT *dht[3];

void setup() {
  for (byte n=0; n<3; n++) {
   dht[n] = new DHT(n+4, DHT11);
   dht[n]->begin();
  }
//dht.begin();
Serial.begin(9600);
}

void loop() {
  delay (2000);
  for (byte n=0; n<3; n++){
  float t = dht[4]->readTemperature();
  if (isnan(t)) {
    Serial.print(F("Failed to read from DHT sensor! № ")); Serial.println(n);
    continue;
  }
  Serial.print(F("Temperature DHT: ")); Serial.print(n);
  Serial.print(F(" - "));  Serial.print(t);
  Serial.println(F("°C "));
  }
}

Что-то я где то не верно сделал. Результат:

Failed to read from DHT sensor! № 0
Failed to read from DHT sensor! № 1
Failed to read from DHT sensor! № 2
 
Да еще через некоторое время зависает все(
 
PS Датчик у меня на пятом пине
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

AsNik пишет:

asam пишет:

Ровно тем же способом что я уже говорил.

#include "DHT.h"


DHT *dht[3];

void setup() {
  for (byte n=0; n<3; n++) {
   dht[n] = new DHT(n+4, DHT11);
   dht[n]->begin();
  }
//dht.begin();
Serial.begin(9600);
}

void loop() {
  delay (2000);
  for (byte n=0; n<3; n++){
  float t = dht[4]->readTemperature();
  if (isnan(t)) {
    Serial.print(F("Failed to read from DHT sensor! № ")); Serial.println(n);
    continue;
  }
  Serial.print(F("Temperature DHT: ")); Serial.print(n);
  Serial.print(F(" - "));  Serial.print(t);
  Serial.println(F("°C "));
  }
}

Что-то я где то не верно сделал. Результат:

Failed to read from DHT sensor! № 0
Failed to read from DHT sensor! № 1
Failed to read from DHT sensor! № 2
 
Да еще через некоторое время зависает все(
 
PS Датчик у меня на пятом пине

 

DHT *dht[3];

float t = dht[4]->readTemperature();

 

Это как понимать?

 

AsNik
Offline
Зарегистрирован: 24.10.2020

Ё, моё.... Ну это уже я совсем что-то сплохел :( Исправил на n  И да, работает. Чудненько. Спасибо.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Надумалось.  Правда, здесь три Dallas18B20. Компилируется без предупреждений, как нащёт работает ли - нинаю. :) 

struct TExample {
protected:
	const TDS18B20& FSensor; // тут запоминается ссылка на сенсор

	TExample() = delete;	// пустой конструктор не разрешен
public:

	TExample(const TDS18B20& ASensor) :FSensor(ASensor) {}; 

	int8_t Read() {
		return FSensor.GetTemperature();
	}
};

TExample SensorArray[] = { 
	*(new TDS18B20(8)),     // Dallas на 8й ноге
	*(new TDS18B20(9)),     // на 9й ноге
	*(new TDS18B20(10))     // и на 10й ноге
};

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

DetSimen пишет:

Надумалось....

деда, ты чЁ средство не разбавленное даешь, у них же голова болетьь будетьь :)))

AsNik
Offline
Зарегистрирован: 24.10.2020

Так то да, сложновато в понимании...

Но Delphi'вый стиль радует глаз :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

xDriver пишет:

деда, ты чЁ средство не разбавленное даешь, у них же голова болетьь будетьь :)))

Дак я ж протрезвел уже. 

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

А кто или что мешает сделать совсем просто, тупо в лоб?

#include "DHT.h"

struct NameStruct {
	DHT dht;
	float f1, f2, f3;
	byte b1, b2, b3;
};

NameStruct nstr [] = {
	{ DHT(4, DHT11), 0,0,0,0,0,0 },
	{ DHT(5, DHT11), 0,0,0,0,0,0 },
	{ DHT(6, DHT11), 0,0,0,0,0,0 }
};


void setup(void) {}
void loop(void) {}

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

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

AsNik пишет:
время между считываниями должно быть не менее двух секунд. Это нужно будет учитывать при опросе датчиков... По ходу нарисовалась еще проблема...

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

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

А кто или что мешает сделать совсем просто, тупо в лоб?

Спасибо. Интересный подход. Я на основе него сделаю тестовый проект и сохраню в качестве шаблона, но если..

ЕвгенийП пишет:

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

...разберусь с этим. Правильно ли я понял, это предостережение к обращению к не созданному объекту?

Но что-то это совсем просто и скорее всего не в этом дело. Ибо в момент инициализации гл. переменных вроде бы и не должно быть обращений к объектам.

 

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

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

Ну на самом деле я именно так примерно и сделал. В методе Loop постоянно идет вызов опроса датчиков, а в нем уже вся логика опроса. Примерно так:

void loop() {
....
readDHTs();
....
}

#define PERIOD_MS 2000
uint32_t msDht = 0;
void readDHTs() {
  if (millis() - msDht >= PERIOD_MS) {
    for n=0; n<COUNT_DHT; n++ {
    //Тут бежим по всем датчикам, считываем проверяем сохраняем
    }
  }
}

 

Но вот подозреваю что логика опроса внутри сильно хромает и именно данный метод у меня получился
самый затратный и по времени и по ресурсам :( (метод и все что для него выделено)
AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

А кто или что мешает сделать совсем просто, тупо в лоб?

#include "DHT.h"

struct NameStruct {
	DHT dht;
	float f1, f2, f3;
	byte b1, b2, b3;
};

NameStruct nstr [] = {
	{ DHT(4, DHT11), 0,0,0,0,0,0 },
	{ DHT(5, DHT11), 0,0,0,0,0,0 },
	{ DHT(6, DHT11), 0,0,0,0,0,0 }
};


void setup(void) {}
void loop(void) {}

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

У меня сейчас так:

struct DHTData {                    //Данные датчика
  DHT * dht;
  char dhtTitle[20];                  //Описание датчика
  float tOn, tOff;                    //Температура включения, выключения
  byte hOn, hOff;                     //Влажность включения, отключения
  float t = NAN, h = NAN;             //Текущая температура и влажность
  float ttmp = 0, htmp = 0;           //Временные данные по температуре и влажности нужны в момент измерения
  float tmin, tmax, hmin, hmax;       //Минимальные и максимальные значения температуры и влажности
  bool f_DHTError;                    //True Если с датчика DHT ничего не считалось
};

DHTData dhts[COUNT_DHT];                          //Массив данных датчиков
byte dhtPins[COUNT_DHT] = {5, 8, 7};              //Массив номеров пинов к которым подключены датчики
byte dhtType[COUNT_DHT] = {DHT11, DHT22, DHT22};  //Типы датчиков

Ну и в Setup создаются настраиваются и запускаются датчики

  for (byte n = 0; n < COUNT_DHT; n++) {
    dhts[n].dht = new DHT(dhtPins[n], dhtType[n]);
    dhts[n].dht->begin();
  }

В моем случае два лишних массива.

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

AsNik пишет:

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

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

AsNik
Offline
Зарегистрирован: 24.10.2020

У структур могут быть свои методы?.... Интересно, сейчас поищу... Но пока не понимаю в этой принципиальной разнице.

AsNik
Offline
Зарегистрирован: 24.10.2020

Хм... структура получается почти как класс по своей структуре) Хотя мало в инете я нашел инфы по этому...Это что-то нечто в #9 такое сделано...

Нет, это пока для меня сложно... Я и так в этом проекте(так как мне отвечают практически одни и те же люди, думаю будет понятно) много чего узнал, и если честно, то дошел до такого уровня, когда от нового становится только хуже понимание. Немного нужно притормозить с нововведениями и переварить текущее... С трудными нововведениями попробую разобраться позже... Спасибо всем за помощь!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AsNik пишет:

Хм... структура получается почти как класс по своей структуре

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

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

AsNik пишет:

У структур могут быть свои методы?

Хороший вопрос. А Вы вообще читаете, что Вам пишут? Методы структур в полный рост использовались в #9

AsNik пишет:

Хм... структура получается почти как класс

Почему "почти как"? Структура - это и есть класс. Безо всяких "почти как". Отличия между ними связаны только с доступом к членам по умолчанию, что не отменяет никаких "классовых" фич.

AsNik пишет:

Ну на самом деле я именно так примерно и сделал. 

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Вот смари.  Абстрактный класс любого моего сенсора. Опрашивается не чаще заданного интервала. 

const uint16_t DEFAULT_READ_PERIOD = 1000;  // По умолчанию период чтения даччика - 1 секунда (1000 мс)

class TCustomSensor : public TClass {
protected:

	uint32_t	FLastReadTime;		// время (millis()), когда сенсор читали последний раз 
	uint16_t	FReadInterval;		// минимальный интервал физического чтения сенсора

	virtual void init(void) = 0; // если сенсору нужна инициализация, то она здесь у потомков
	
	virtual void internalRead(void)  = 0; // физическое чтение даччика, у всех потомков разная

public:

	TCustomSensor() {								// в конструкторе: 
		SetReadInterval(DEFAULT_READ_PERIOD);       // ... установим интервал чтения по умолчанию
		FLastReadTime = 0 - DEFAULT_READ_PERIOD - 1;// ... настроим время прошлого доступа, чтоб точно прочитать после сброса  
		classname = F("CustomSensor");              // ... присвоим имя классу
	}

	void SetReadInterval(const uint16_t ANewReadInterval) {  // установим новый интервал чтения даччика
		FReadInterval = ANewReadInterval;
	}


	void Read(void) {   // сопсно, функция чтения даччика, одна на всех потомков


		uint32_t now = millis();   // скока щас время? 
		if (now - FLastReadTime < FReadInterval) return; // если даччик недавно читали, уходим

		FLastReadTime = now; // иначе запомним когда даччик читали в послед. раз

		internalRead(); // и прочитаем его уже, наконец

	}

};

 

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

А Вы вообще читаете, что Вам пишут? Методы структур в полный рост использовались в #9

Зря Вы так. Я вообще-то обратил на это внимание в #20

И вообще я стараюсь внимательно изучать все ваши комментарии, но признаюсь, в меру своей безграмотности в данном вопросе, тяжко мне дается многое. Очень сильно сбивает "знание" делфи, которым я увлекался лет 15 назад. На данный момент могу сказать, что делфи знаю меньше чем си, а си вообще практически не знаю :(

ЕвгенийП пишет:

Ну, на самом деле, Вы сделали принципиально не так.

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

ЕвгенийП пишет:

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

Так оно и так вроде там все и работает. Я только "иногда" беру готовые значения с датчиков. Хотя идею в #23 понял. Но у меня пока так:

#define PERIODDHTMS 2200
uint32_t msDht = 0;
byte n = 0;
void readDHT() {
  if (millis() - msDht >= PERIODDHTMS) {
    for (byte i = 0; i < COUNT_DHT; i++) {
      if (n < 5) {
        if (dhts[i].ttmp == 0 && n > 0) continue;
        float t = dhts[i].dht->readTemperature();     // Read temperature as Celsius (the default)
        if (dhts[i].htmp == 0 && n > 0) continue;
        float h = dhts[i].dht->readHumidity();
        if (isnan(t) || isnan(h)) {                   // Check if any reads failed and exit early (to try again).
          dhts[i].ttmp = dhts[i].htmp = 0;
          dhts[i].f_DHTError = true;
          continue;
        }
        dhts[i].ttmp += t;
        dhts[i].htmp += h;
      } else {
        dhts[i].t = dhts[i].ttmp / n;
        dhts[i].h = dhts[i].htmp / n;
        if (isnan(dhts[i].tmin)) dhts[i].tmin = dhts[i].t;
        else dhts[i].tmin = min(dhts[i].t, dhts[i].tmin);
        if (isnan(dhts[i].tmax)) dhts[i].tmax = dhts[i].t;
        else dhts[i].tmax = max(dhts[i].t, dhts[i].tmax);
        if (isnan(dhts[i].hmin)) dhts[i].hmin = dhts[i].h;
        else dhts[i].hmin = min(dhts[i].h, dhts[i].hmin);
        if (isnan(dhts[i].hmax)) dhts[i].hmax = dhts[i].h;
        else dhts[i].hmax = max(dhts[i].h, dhts[i].hmax);
        dhts[i].f_DHTError = (dhts[i].ttmp ==0 && dhts[i].htmp == 0);
        dhts[i].ttmp = dhts[i].htmp = 0;
      }
    }
    if (n < 5) n++; else n = 0;
    do {
      msDht += PERIODDHTMS;
      if (msDht < PERIODDHTMS) break;         // переполнение uint32_t
    } while (msDht < millis() - PERIODDHTMS); // защита от пропуска шага
  }
}

ЗЫЖ А как вы скрытый текст делаете? Вроде нашел)

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

Вот смари.  Абстрактный класс любого моего сенсора. Опрашивается не чаще заданного интервала. 

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

ЗЫЖ. А почему пишешь в стиле Делфи? :) T у классов с F приватные с А параметры....

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

основное, физическое чтение чего-либо происходит в абстракном методе internalRead()

например, DS18B20 читается так

	void internalRead() override {

		if (ReadData()) { // здесь читаем память Далласа

			int8_t temp = (FDallasMemory[1] << 4) | (FDallasMemory[0] >> 4); // выделяем из нее температуры

			if (temp == FTemperature) return;

			// если температура отличается от ранее прочитанной, 
			// уведомим приложение о том, что температура изменилась 

			FTemperature = temp;
			PostMessage(msg_TemperatureChanged, FTemperature); 
		}
		else 	
			PostMessage(msg.Error, err_OneWire_CRCError); // или уведомим, что неверно прочитали даччик

	}

А для фоторезистора способ чтения будет совершенно другой.  Но в loop() вызовы будут одинаковы

dallas.Read();

photo.Read();

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

loop() не загромождён всякими if (millis()-lastmillis>ХЗ) doSomething().

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AsNik пишет:

ЗЫЖ. А почему пишешь в стиле Делфи? :) T у классов с F приватные с А параметры....

Привык за 24 года. 

AsNik
Offline
Зарегистрирован: 24.10.2020

#23, #26 Как это круто! Я, глядя на такие вещи, понимаю что в си я не полный ноль а в минусе даже :(

Эх, зря я на полтора десятка лет забросил хобби...

AsNik
Offline
Зарегистрирован: 24.10.2020

Т.е. если я правильно понял, то получится нечто такое:

//struct DHTData {                    //Данные датчика
//  DHT * dht;
//  char dhtTitle[20];                  //Описание датчика
//  float tOn, tOff;                    //Температура включения, выключения
//  byte hOn, hOff;                     //Влажность включения, отключения
//  float t = NAN, h = NAN;             //Текущая температура и влажность
//  float ttmp = 0, htmp = 0;           //Временные данные по температуре и влажности нужны в момент измерения
//  float tmin, tmax, hmin, hmax;       //Минимальные и максимальные значения температуры и влажности
//  bool f_DHTError;                    //True Если с датчика DHT ничего не считалось
//};

TSensorDHT dths[COUNT_DHT]; 

А все что было в структуре, перекачует в унаследованный от TCosmomSensor в TSensorDHT?

Весь мой код (логику) опроса датчика так же поместить в класс.

Ну и в начале(Setup) создать массив сенсоров, а потом в loop просто их "шевелить" методом internalRead и просто работать с их данными для вывода на экран и обработка.... Верно?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если до завтра подождёшь, напишем тебе TDHTSensor.  Счас некада. 

AsNik
Offline
Зарегистрирован: 24.10.2020

Ок. Возможно я решусь на переделывание своего проекта с нуля)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AsNik пишет:

Я ... понимаю что в си я не полный ноль а в минусе даже :(

Не расстраивайся, я тоже.  

в loop() будет дёргаца Read(), который сам, не чаще заданного интервала будет вызывать internalRead() в котором, сопсно, и происходит чтение железа (любого, которое напишешь, BMP280, АМ2320, SHT10, или DS18B20). В том и цимес, что поведение единообразно, а различия программируются всего одной виртуальной функцией. 

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

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

Почитай пока, будешь знать о чём идёт речь.  

Ну это(сообщения) вообще классно.... я даже и думать пока об этом не хотел... Практически программирование как под винду получается...

Я еще в #26 обратил внимание на PostMessage, но подумал "показалось"...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ты, наерна, удивишься и расстроишься, но больше половины описанных здесь параметров нах не нужны

//struct DHTData {                    //Данные датчика
//  DHT * dht;
//  char dhtTitle[20];                  //Описание датчика
//  float tOn, tOff;                    //Температура включения, выключения
//  byte hOn, hOff;                     //Влажность включения, отключения
//  float t = NAN, h = NAN;             //Текущая температура и влажность
//  float ttmp = 0, htmp = 0;           //Временные данные по температуре и влажности нужны в момент измерения
//  float tmin, tmax, hmin, hmax;       //Минимальные и максимальные значения температуры и влажности
//  bool f_DHTError;                    //True Если с датчика DHT ничего не считалось
//};

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

Второе. Существует два пути для создания нашего нового класса TDHTSensor, это либо обёртка над существующим классом DHT, например, от Adafruit, либо самостоятельное чтение шины, без любых библиотек, т.е самодостаточный класс.  Первый путь пока проще, поэтому падём им. 

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

(я всегда температуру мерию в целых, с любыми даччиками, так проще программировать, занимает меньше памяти и, самое главное, мне пофиг сколько на улице гра, -25 или -25.3, мёрзну я в обоих случаях одинаково) 

 

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

если используется для анализа работы железа, то и целого Мира бишь двух знаков после запятой - мало )))
PS всё больше проникаюсь концепцией C++

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

Ты, наерна, удивишься и расстроишься, но больше половины описанных здесь параметров нах не нужны

 

Сенсор вообще не должен вмешиваться в логику приложения, ему пофиг, когда что включать и когда что отключать, это должна знать и занимаца сама программа.

Так то да, все верно. Но на данный момент мне так удобнее. Поясню. У меня есть три датчика. Ну или два и один общий. Я пока первый раз делаю... а зима покажет как лучше. Так вот у двух датчиков свои параметры(диапазоны) вкл/выкл. (Собсно в данных датчика - границы диапазонов. А решение по реагированию на данные с датчика конечно в другом месте.) Но при расчетах будут учтены данные с третьего датчика. А его параметры(диапазоны) - ну пусть будут. Может задействую.

По поводу точности. С двух датчиков(с одного точно) нужна точность 0.5, точнее до десятых, но я его обрабатываю по 0.5) Это касаемо температуры. А влажность, да. Точность такая не нужна. Поэтому у меня по влажности частично переменные byte. (Кстати, да... нужно еще раз пересмотреть по типам переменных влажности, кое где исправить)

DetSimen пишет:

два пути для создания нашего нового класса TDHTSensor, это либо обёртка над существующим классом DHT, например, от Adafruit, либо самостоятельное чтение шины, без любых библиотек, т.е самодостаточный класс.  Первый путь пока проще, поэтому падём им.

Спасибо конечно за желание помочь... даже не помочь а.... Если это будет не ущерб Вашего времени... Просто я сейчас не уверен смогу ли я воспользоваться новым классом... Посмотрев код на гитхабе даже Morze - для меня это пока сложно( Просто я если не понимаю, даже если это работает, я стараюсь этим не пользоваться.... ну только если безвыходная ситуация (например LiquidCrystal_I2C.h - я даже туда не лезу, работает - ну и хорошо)

Но на всякий случай это по либе которая у меня для DHT:

name=DHT sensor library
version=1.4.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors
paragraph=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors
category=Sensors
url=https://github.com/adafruit/DHT-sensor-library
architectures=*
depends=Adafruit Unified Sensor

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AsNik пишет:

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

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

Но.  Если тебе надо сделать быстро - делай по своему.  Я тогда буду неспешно готовить цикл статей на тему "Архитектура Windows в AVR приложениях" 

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

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

Полностью согласен. Я стараюсь к этому придти, но пока не очень, но получается....

Если не сложно, можно какой нибудь минимальный пример правильного использования связки Sensor - Alarm - Основной код. Ну прям просто и для чайников. Саму суть... Теоретически вроде понимаю. Но на практике почему-то код обрастает.... вижу, что не правильно, но с трудом рожденный код страшно переделывать)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Видишь ли, мой код полностью message-driven и рассказывать, как это работает, надо с нуля, а у тебя времени нет, зима близко. :)   Так что делай пока как умеешь, а я в статьях всё подробно распишу. 

Ну и никому из здешних обитателей не возбраняется задавать вопросы по электропочте elf-basic@ya.ru 

Feofan
Offline
Зарегистрирован: 28.05.2017

Цитата:

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

AsNik
Offline
Зарегистрирован: 24.10.2020

Спасибо :) Так-то у меня уже этих копий.... уже путаюсь в них) Ладно, разберемся... Ну если что не сочтите мои глупые вопросы за наглость. Ну реально могу спросить то, что вроде уже делал, но шаг в сторону и снова тупик. Это по большей части связано с указателями и бинарными данными - в них я тоже не очень :( всякие >> <<.... Ну никак в своей голове не могу удержать некоторую информацию.... Вот чё "сто лет назад" было помню, а новое - ну ужас какой-то( (хочется поставить веселый смайл, но увы....)

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

электропочте

Каждый раз где вижу это твое слово - улыбаюсь)

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

DetSimen пишет:

  Я тогда буду неспешно готовить цикл статей на тему "Архитектура Windows в AVR приложениях" 

неужели увидим нечто подобное 21 прерыванию в DOS?

PS вырисовалась непонятка, куча различных прерываний есть, а менеджер - отсутствует... и тянет это одеяло на себя каждое из желающих воспользоваться этим приложение! НЕПОРЯДОК ОДНАКО!!!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ua6em пишет:

DetSimen пишет:

  Я тогда буду неспешно готовить цикл статей на тему "Архитектура Windows в AVR приложениях" 

неужели увидим нечто подобное 21 прерыванию в DOS?

Нет. Ты в Windows прерывания вапще видел?

AsNik
Offline
Зарегистрирован: 24.10.2020

прерывания и сообщения - это "немного" разные вещи. Винда основана на сообщениях

Получило окно (а им(окном)может быть обычная кнопка) сообщение WM_PAINT - значит пора себя отрисовать

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

DetSimen пишет:

ua6em пишет:

DetSimen пишет:

  Я тогда буду неспешно готовить цикл статей на тему "Архитектура Windows в AVR приложениях" 

неужели увидим нечто подобное 21 прерыванию в DOS?

Нет. Ты в Windows прерывания вапще видел?

до виндовс не дорос, застыл на ДОСе, пусть саапщения, но до железа то они как-то добираются...

Просто анализирую, SoftwareSerial это библиотека из поставки IDE, тянет всё на себя, как-то это не по человечески, те же грабли, через которые прошёл Билл Гейтс???

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

PS вырисовалась непонятка, куча различных прерываний есть, а менеджер - отсутствует... и тянет это одеяло на себя каждое из желающих воспользоваться этим приложение! НЕПОРЯДОК ОДНАКО!!!

В микроконтроллере всегда есть только единственное приложение. Так что никакого непорядка нет.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

Просто анализирую, SoftwareSerial это библиотека из поставки IDE, тянет всё на себя, как-то это не по человечески, те же грабли, через которые прошёл Билл Гейтс???

Издержки концепции Ардуино: если SoftwareSerial не будет "тянуть все на себя", ему потребуется дополнительная настройка (что именно можно "тянуть"), объяснить которую, не привлекая внутреннюю архитектуру МК, вряд ли возможно.

Концепция подходит только для простых проектов, а два претендента на PCINT (которых вообще в Ардуино нет) - это уже сложный проект.

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

andriano пишет:

Концепция подходит только для простых проектов, а два претендента на PCINT (которых вообще в Ардуино нет) - это уже сложный проект.

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

PS ОНКЕЛЬ вон пишет на честном С,взяв управление всем и вся в свои руки, о чём и говорит, а хотелось бы в стиле ардуино
 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

andriano пишет:

Концепция подходит только для простых проектов, а два претендента на PCINT (которых вообще в Ардуино нет) - это уже сложный проект.

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

И как объяснить новичкам необходимость менеджера PCINT, если они понятия не имеют, что это такое?

 

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