Bitte intiberius28 hat geschrieben: ↑17.12.2021, 19:57[...]
1,) HM-WDS40-TH-I-BME280_OLED2.) HB-UNI-Sen-TEMP-DS18B20-OLEDCode: Alles auswählen
//- ----------------------------------------------------------------------------------------------------------------------- // AskSin++ // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ // 2019-10-02 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //- ----------------------------------------------------------------------------------------------------------------------- // ci-test=yes board=328p aes=no // define this to read the device id, serial and device type from bootloader section // #define USE_OTA_BOOTLOADER // #define USE_LCD //bei Verwendung des LCD Displays https://www.aliexpress.com/item/1435066364.html #define USE_OLED 1 #ifdef USE_OLED #include <Wire.h> #include "SSD1306Ascii.h" #include "SSD1306AsciiWire.h" #define I2C_ADDRESS 0x3C SSD1306AsciiWire oled; #endif //======================================================== #define EI_NOTEXTERNAL #include <EnableInterrupt.h> #include <AskSinPP.h> #include <LowPower.h> #include <MultiChannelDevice.h> #include <sensors/Bme280.h> #ifdef USE_LCD #include "displays/Lcd4seg.h" #define LCD_CS 6 #define LCD_WR 3 #define LCD_DATA 7 #define LCD_INTERVAL_SECONDS 10 #endif // we use a Pro Mini // Arduino pin for the LED // D4 == PIN 4 on Pro Mini #define LED_PIN 4 // Arduino pin for the config button // B0 == PIN 8 on Pro Mini #define CONFIG_BUTTON_PIN 8 //----------------------------------------------------------------------------------------- //Korrektur von Temperatur und Luftfeuchte //Einstellbarer OFFSET für Temperatur -> gemessene Temp +/- Offset = Angezeigte Temp. #define OFFSETtemp 0 //z.B -50 ≙ -5°C / 50 ≙ +5°C //Einstellbarer OFFSET für Luftfeuchte -> gemessene Luftf. +/- Offset = Angezeigte Luftf. #define OFFSEThumi 0 //z.B -10 ≙ -10%RF / 10 ≙ +10%RF //----------------------------------------------------------------------------------------- // number of available peers per channel #define PEERS_PER_CHANNEL 6 //seconds between sending messages #define MSG_INTERVAL 180 // all library classes are placed in the namespace 'as' using namespace as; // define all device properties const struct DeviceInfo PROGMEM devinfo = { {0x87, 0x6f, 0x99}, // Device ID "JPTH10I999", // Device Serial {0x00, 0x3f}, // Device Model Indoor 0x10, // Firmware Version as::DeviceType::THSensor, // Device Type {0x01, 0x01} // Info Bytes }; /** Configure the used hardware */ typedef AvrSPI<10, 11, 12, 13> SPIType; typedef Radio<SPIType, 2> RadioType; typedef StatusLed<LED_PIN> LedType; typedef AskSin<LedType, BatterySensor, RadioType> Hal; Hal hal; #ifdef USE_LCD LCDToggleTH<LCD4SEG<LCD_CS, LCD_WR, LCD_DATA>> lcd; #endif class WeatherEventMsg : public Message { public: void init(uint8_t msgcnt, int16_t temp, uint8_t humidity, bool batlow) { uint8_t t1 = (temp >> 8) & 0x7f; uint8_t t2 = temp & 0xff; if ( batlow == true ) { t1 |= 0x80; // set bat low bit } Message::init(0xc, msgcnt, 0x70, BIDI | WKMEUP, t1, t2); pload[0] = humidity; } }; class WeatherChannel : public Channel<Hal, List1, EmptyList, List4, PEERS_PER_CHANNEL, List0>, public Alarm { WeatherEventMsg msg; int16_t temp; uint8_t humidity; Bme280 bme280; uint16_t millis; public: WeatherChannel () : Channel(), Alarm(5), temp(0), humidity(0), millis(0) {} virtual ~WeatherChannel () {} // here we do the measurement void measure () { DPRINT("Measure...\n"); bme280.measure(); temp = bme280.temperature() + OFFSETtemp; humidity = bme280.humidity() + OFFSEThumi; DPRINT("T/H = " + String(temp) + "/" + String(humidity) + "\n"); //========================================================================= #ifdef USE_OLED oled.clear(); //oled.setFont(System5x7); // Auswahl der Schriftart oled.println("JPTH10I999"); oled.println("Temp., Feucht.:"); //oled.setFont(Arial_bold_14); //4 Zeilen a 16 Zeichen oled.println("T = " + String(temp/10.) + " C"); oled.println("H = "+ String(humidity) + " %"); #endif //========================================================================== } virtual void trigger (__attribute__ ((unused)) AlarmClock& clock) { uint8_t msgcnt = device().nextcount(); // reactivate for next measure tick = delay(); clock.add(*this); measure(); #ifdef USE_LCD lcd.setValues(temp, humidity, device().battery().low()); #endif msg.init(msgcnt, temp, humidity, device().battery().low()); if (msgcnt % 20 == 1) device().sendPeerEvent(msg, *this); else device().broadcastEvent(msg, *this); } uint32_t delay () { return seconds2ticks(MSG_INTERVAL); } void setup(Device<Hal, List0>* dev, uint8_t number, uint16_t addr) { Channel::setup(dev, number, addr); bme280.init(); sysclock.add(*this); #ifdef USE_LCD lcd.init(); lcd.setToggleTime(LCD_INTERVAL_SECONDS); #endif } uint8_t status () const { return 0; } uint8_t flags () const { return 0; } }; typedef MultiChannelDevice<Hal, WeatherChannel, 1> WeatherType; WeatherType sdev(devinfo, 0x20); ConfigButton<WeatherType> cfgBtn(sdev); void setup () { DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER); #ifdef USE_OLED Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, I2C_ADDRESS); //oled.setFont(fixed_bold10x15); oled.setFont(Verdana12_italic); //oled.setFont(System5x7); // Auswahl der Schriftart //oled.setFont(lcdnums12x16); //oled.setFont(fixednums15x31); oled.clear(); //Löschen der aktuellen Displayanzeige oled.println("Viel"); //Text in der ersten Zeile. "Println" sorgt dabei für einen Zeilensprung. oled.println("Erfolg!!!"); // Text in der zweiten Zeile. Da es keine dritte Zeile gibt, wird hier kein Zeilenumsprung benötigt. delay (2000); #endif sdev.init(hal); hal.initBattery(60UL * 60, 22, 19); buttonISR(cfgBtn, CONFIG_BUTTON_PIN); /* Set frequency for CC1101 //FreqTest schreibt die Frequenz in das Eprom falls das nicht funtioniert, dann kann hier die ermittelte Frequenz eingestellt werden // ermittelt wurde 0x2165BA hal.radio.initReg(CC1101_FREQ2, 0x21); hal.radio.initReg(CC1101_FREQ1, 0x65); hal.radio.initReg(CC1101_FREQ0, 0xBA);*/ sdev.initDone(); } void loop() { bool worked = hal.runready(); bool poll = sdev.pollRadio(); if ( worked == false && poll == false ) { hal.activity.savePower<Sleep<>>(hal); } }
Code: Alles auswählen
//- ----------------------------------------------------------------------------------------------------------------------- // AskSin++ // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ // 2018-03-24 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //- ----------------------------------------------------------------------------------------------------------------------- // define this to read the device id, serial and device type from bootloader section // #define USE_OTA_BOOTLOADER #define USE_LCD 0 //#define LCD_ADDRESS 0x3f #define LCD_ADDRESS 0x27 #define USE_OLED 1 #ifdef USE_OLED #include <Wire.h> #include "SSD1306Ascii.h" #include "SSD1306AsciiWire.h" #define I2C_ADDRESS 0x3C SSD1306AsciiWire oled; #endif //======================================================== #define EI_NOTEXTERNAL #include <EnableInterrupt.h> #include <AskSinPP.h> #include <LowPower.h> #include <Register.h> #include <MultiChannelDevice.h> #ifdef USE_LCD //use this LCD lib: https://github.com/marcoschwartz/LiquidCrystal_I2C #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(LCD_ADDRESS, 20, 4); #endif #include <OneWire.h> #include <sensors/Ds18b20.h> #define MAX_SENSORS 8 // Arduino Pro mini 8 Mhz // Arduino pin for the config button #define CONFIG_BUTTON_PIN 8 #define LED_PIN 4 // number of available peers per channel #define PEERS_PER_CHANNEL 6 //DS18B20 Sensors connected to pin OneWire oneWire(3); // all library classes are placed in the namespace 'as' using namespace as; // define all device properties const struct DeviceInfo PROGMEM devinfo = { {0xf3, 0x01, 0x01}, // Device ID "UNITEMP001", // Device Serial {0xF3, 0x01}, // Device Model 0x10, // Firmware Version as::DeviceType::THSensor, // Device Type {0x01, 0x01} // Info Bytes }; /** Configure the used hardware */ typedef AvrSPI<10, 11, 12, 13> SPIType; typedef Radio<SPIType, 2> RadioType; typedef StatusLed<LED_PIN> LedType; typedef AskSin<LedType, BatterySensor, RadioType> BaseHal; class Hal : public BaseHal { public: void init (const HMID& id) { BaseHal::init(id); battery.init(seconds2ticks(60UL * 60), sysclock); //battery measure once an hour battery.low(22); battery.critical(18); } bool runready () { return sysclock.runready() || BaseHal::runready(); } } hal; DEFREGISTER(UReg0, MASTERID_REGS, DREG_LOWBATLIMIT, 0x21, 0x22) class UList0 : public RegList0<UReg0> { public: UList0 (uint16_t addr) : RegList0<UReg0>(addr) {} bool Sendeintervall (uint16_t value) const { return this->writeRegister(0x21, (value >> 8) & 0xff) && this->writeRegister(0x22, value & 0xff); } uint16_t Sendeintervall () const { return (this->readRegister(0x21, 0) << 8) + this->readRegister(0x22, 0); } void defaults () { clear(); lowBatLimit(22); Sendeintervall(180); //Sendeintervall(60); } }; DEFREGISTER(UReg1, 0x01, 0x02, 0x03, 0x04) class UList1 : public RegList1<UReg1> { public: UList1 (uint16_t addr) : RegList1<UReg1>(addr) {} bool Offset (int32_t value) const { return this->writeRegister(0x01, (value >> 24) & 0xff) && this->writeRegister(0x02, (value >> 16) & 0xff) && this->writeRegister(0x03, (value >> 8) & 0xff) && this->writeRegister(0x04, (value) & 0xff) ; } int32_t Offset () const { return ((int32_t)(this->readRegister(0x01, 0)) << 24) + ((int32_t)(this->readRegister(0x02, 0)) << 16) + ((int32_t)(this->readRegister(0x03, 0)) << 8) + ((int32_t)(this->readRegister(0x04, 0))) ; } void defaults () { clear(); Offset(0); } }; int32_t Offsets[MAX_SENSORS]; class WeatherEventMsg : public Message { public: void init(uint8_t msgcnt, Ds18b20* sensors, bool batlow, uint8_t channelFieldOffset) { Message::init(0x16, msgcnt, 0x53, (msgcnt % 20 == 1) ? (BIDI | WKMEUP) : BCAST, batlow ? 0x80 : 0x00, 0x41 + channelFieldOffset); int16_t t0 = sensors[0 + channelFieldOffset].temperature() + Offsets[0 + channelFieldOffset]; int16_t t1 = sensors[1 + channelFieldOffset].temperature() + Offsets[1 + channelFieldOffset]; int16_t t2 = sensors[2 + channelFieldOffset].temperature() + Offsets[2 + channelFieldOffset]; int16_t t3 = sensors[3 + channelFieldOffset].temperature() + Offsets[3 + channelFieldOffset]; pload[0] = (t0 >> 8) & 0xff; pload[1] = (t0) & 0xff; pload[2] = 0x42 + channelFieldOffset; pload[3] = (t1 >> 8) & 0xff; pload[4] = (t1) & 0xff; pload[5] = 0x43 + channelFieldOffset; pload[6] = (t2 >> 8) & 0xff; pload[7] = (t2) & 0xff; pload[8] = 0x44 + channelFieldOffset; pload[9] = (t3 >> 8) & 0xff; pload[10] = (t3) & 0xff; } }; class WeatherChannel : public Channel<Hal, UList1, EmptyList, List4, PEERS_PER_CHANNEL, UList0> { public: WeatherChannel () : Channel() {} virtual ~WeatherChannel () {} void configChanged() { //DPRINT(F("(")); DDEC(number()); DPRINTLN(F(") Config changed List1")); DPRINT(F("OFFSET: ")); DDECLN(this->getList1().Offset()); Offsets[number() - 1] = this->getList1().Offset(); } uint8_t status () const { return 0; } uint8_t flags () const { return 0; } }; class UType : public MultiChannelDevice<Hal, WeatherChannel, MAX_SENSORS, UList0> { class SensorArray : public Alarm { UType& dev; public: uint8_t sensorcount; Ds18b20 sensors[MAX_SENSORS]; SensorArray (UType& d) : Alarm(0), dev(d), sensorcount(0) {} virtual void trigger (__attribute__ ((unused)) AlarmClock& clock) { tick = delay(); sysclock.add(*this); Ds18b20::measure(sensors, sensorcount); DPRINT(F("Temperaturen: | ")); #ifdef USE_OLED oled.clear(); oled.println("UNITEMP001"); oled.println("Temperaturen:"); #endif for (int i = 0; i < MAX_SENSORS; i++) { DDEC(sensors[i].temperature()); DPRINT(" | "); #ifdef USE_OLED //oled.println(sensors[0].temperature()); //uint8_t x = (i % 2 == 0 ? 0 : 10); //uint8_t y = i / 2; //lcd.setCursor(x, y); //oled.clear(); String s_temp1 = " --.-"; if ((i + 1) <= sensorcount) { s_temp1 = (String)((float)sensors[i].temperature() / 10.0); s_temp1 = s_temp1.substring(0, s_temp1.length() - 1); if (sensors[i].temperature() < 1000 && sensors[i].temperature() >= 0) s_temp1 = " " + s_temp1; //oled.println(s_temp1); } //String disp_temp1 = String(i + 1) + ":" + s_temp1 + (char)223 + "C "; String disp_temp1 = String(i + 1) + ":" + s_temp1 + " C "; DPRINTLN(disp_temp1); int odd = i % 2; if (odd == 1) { oled.println(disp_temp1); } else { oled.print(disp_temp1); }; #endif #ifdef USE_LCD uint8_t x = (i % 2 == 0 ? 0 : 10); uint8_t y = i / 2; lcd.setCursor(x, y); String s_temp = " --.-"; if ((i + 1) <= sensorcount) { s_temp = (String)((float)sensors[i].temperature() / 10.0); s_temp = s_temp.substring(0, s_temp.length() - 1); if (sensors[i].temperature() < 1000 && sensors[i].temperature() >= 0) s_temp = " " + s_temp; } String disp_temp = String(i + 1) + ":" + s_temp + (char)223 + "C "; lcd.print(disp_temp); #endif } DPRINTLN(""); WeatherEventMsg& msg = (WeatherEventMsg&)dev.message(); //Aufteilung in 2 Messages, da sonst die max. BidCos Message Size (0x1a)? überschritten wird msg.init(dev.nextcount(), sensors, dev.battery().low(), 0); dev.send(msg, dev.getMasterID()); #if MAX_SENSORS > 4 _delay_ms(250); msg.init(dev.nextcount(), sensors, dev.battery().low(), 4); dev.send(msg, dev.getMasterID()); #endif } uint32_t delay () { uint16_t _txMindelay = 180; _txMindelay = dev.getList0().Sendeintervall(); if (_txMindelay == 0) _txMindelay = 180; return seconds2ticks(_txMindelay); } } sensarray; public: typedef MultiChannelDevice<Hal, WeatherChannel, MAX_SENSORS, UList0> TSDevice; UType(const DeviceInfo& info, uint16_t addr) : TSDevice(info, addr), sensarray(*this) {} virtual ~UType () {} virtual void configChanged () { TSDevice::configChanged(); DPRINTLN("Config Changed List0"); DPRINT("LOW BAT Limit: "); DDECLN(this->getList0().lowBatLimit()); this->battery().low(this->getList0().lowBatLimit()); DPRINT("Sendeintervall: "); DDECLN(this->getList0().Sendeintervall()); } void init (Hal& hal) { TSDevice::init(hal); sensarray.sensorcount = Ds18b20::init(oneWire, sensarray.sensors, MAX_SENSORS); DPRINT("Found "); DDEC(sensarray.sensorcount); DPRINTLN(" DS18B20 Sensors"); #ifdef USE_LCD lcd.setCursor(2, 3); lcd.print("Found Sensors: " + String(sensarray.sensorcount)); #endif sensarray.set(seconds2ticks(5)); sysclock.add(sensarray); } }; UType sdev(devinfo, 0x20); ConfigButton<UType> cfgBtn(sdev); void setup () { DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER); memset(Offsets, 0, MAX_SENSORS); DDEVINFO(sdev); #ifdef USE_LCD lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("UNI-Sen-TEMP-DS18B20"); lcd.setCursor(5, 1); lcd.print((char*)serial); HMID temp; sdev.getDeviceID(temp); lcd.setCursor(7, 2); lcd.print(temp, HEX); #endif #ifdef USE_OLED Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, I2C_ADDRESS); oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); //Löschen der aktuellen Displayanzeige oled.println("Viel"); //Text in der ersten Zeile. "Println" sorgt dabei für einen Zeilensprung. oled.println("Erfolg!!!"); // Text in der zweiten Zeile. Da es keine dritte Zeile gibt, wird hier kein Zeilenumsprung benötigt. delay (2000); #endif sdev.init(hal); buttonISR(cfgBtn, CONFIG_BUTTON_PIN); sdev.initDone(); } void loop() { bool worked = hal.runready(); bool poll = sdev.pollRadio(); if ( worked == false && poll == false ) { if ( hal.battery.critical() ) { hal.activity.sleepForever(hal); } hal.activity.savePower<Sleep<>>(hal); } }
Code: Alles auswählen
[code][ /code]
Ansonsten, Danke, dass du deine Arbeit mit uns teilst!