AskSin++ Library

Begonnen von papa, 08 September 2016, 11:11:25

Vorheriges Thema - Nächstes Thema

papa

Also ein 8 Kanal Schaltaktor wäre sicherlich recht unproblematisch. Die Ausgänge könnten mit dem MCP23008 geschaltet werden. Dafür gibt es auch ne Arduino-Library. Die Taster kommen alle direkt an die Pins des ATMega328 ran. Unter Umständen sollte noch ein externer EEProm für die Peerlisten mit drauf - z.B. at24c32 mit 4k.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

Klaus0815

Wäre es dann nicht einfacher, einen STM32 zu nutzen? Gibt es dazu auch bereits Platinenlayouts?

Muss mal schauen was ich mache, vielleicht läuft es doch auch einfach auf 2 Deiner universal-Basis-Platinen raus, damit müsste es doch auch gehen?

Das ELV-Board wäre halt schön gewesen, da es genügend Ein/Ausgänge mitbringt, die Ausgänge bereits gepuffert sind.
DIe benutzen übrigens auch ein externes EEPROM


papa

Zitat von: Klaus0815 am 18 Februar 2018, 13:34:31
Wäre es dann nicht einfacher, einen STM32 zu nutzen? Gibt es dazu auch bereits Platinenlayouts?
Wahrscheinlich ja. Nein.
Zitat von: Klaus0815 am 18 Februar 2018, 13:34:31
Muss mal schauen was ich mache, vielleicht läuft es doch auch einfach auf 2 Deiner universal-Basis-Platinen raus, damit müsste es doch auch gehen?
Sollte gehen. Sind dann halt eben 2 Devices.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

Tom Major

Ich bin kürzlich bei der Suche nach Anleitungen für eigene HomeMatic Sender hier gelandet, ein beeindruckendes Projekt, tolle Arbeit, vielen Dank.

Eine kurze Frage hätte ich. Ich habe mir einige Beispiele in \examples auf github angeschaut. Ich möchte ein paar Geräte wie den HM-SCI-3-FM aufbauen
https://www.elv.de/homematic-kontakt-interface-fuer-oeffner-und-schliesserkontake-komplettbausatz.html
dieser hat ja im WebUI einen Offen- und Geschlossen Zustand.

Ich habe mir z.B. HM-RC-8.ino angeschaut, ich vermute aber das wäre nicht 100% richtig, da dort ein Zustand Taste gedrückt übertragen wird und wahrscheinlich der Befehl wiederholt wird solange die Taste gedrückt ist.
Wie würde ich einen "statischen" Offen/Geschlossen Kontakt wie der HM-SCI-3-FM im Arduino Code konfigurieren? Also einen Kontakt der länger seinen Zustand halten kann und nur bei Änderung das an die Zentrale meldet?

Vielen Dank & Grüße,
Tom
Früher: FHEM 5.x
Jetzt: RaspberryMatic / ioBroker

jp112sdl

Zitat von: Tom Major am 18 Februar 2018, 19:44:52
Ich möchte ein paar Geräte wie den HM-SCI-3-FM aufbauen

Moin!
Ich habe aus dem ThreeState-Sketch des RHS einen HM-SCI3-FM abgewandelt.
Funktioniert bestens.
Code ist hier: https://github.com/jp112sdl/Beispiel_AskSinPP/tree/master/examples/HM-SCI3-FM

Tom Major

Vielen Dank, jp112sdl, für den link, das hilft mir weiter.

Ich versuche mir ein grundsätzliches Verständnis über den notwendigen code für so einen sketch zu schaffen,
z.B. sowas hier:
DEFREGISTER(Reg1,CREG_AES_ACTIVE,CREG_MSGFORPOS,CREG_EVENTDELAYTIME,CREG_LEDONTIME,CREG_TRANSMITTRYMAX)
...

und viele andere Stellen, gibt es da irgendwo Docs um das zu verstehen?
(außer der Variante, die kompletten sourcen zu lesen und versuchen zu begreifen  :-\)
Danke,
Früher: FHEM 5.x
Jetzt: RaspberryMatic / ioBroker

jp112sdl

Zitat von: Tom Major am 18 Februar 2018, 23:47:02
... gibt es da irgendwo Docs um das zu verstehen?

Nein, gibt es leider nicht. Der Code ist die Doku  :D

Ich bin auch kein Profi-Programmierer und in den Libs steckt ganz viel neue Syntax für mein Hirn... alles keine leichte Kost.
Zumal jeder einen anderen Programmierstil hat und man erstmal durchsteigen muss. So versteht ein Hamburger den Münchner schlecht, auch wenn beide deutsch sprechen.  :)

Ich sag mir halt: Kaputt machen kann ich nichts. Hab viel rumprobiert...
Vieles hat geklappt, ein paar Sachen haben nicht geklappt.

Aber die Zusammenarbeit mit papa klappt sehr gut!
Der HM-Sec-SD Sketch ist erst vor kurzem auf meinen Wunsch entstanden, wobei er den Code geschrieben hat und ich ihn pausenlos mit Log- und Testreihen versorgt habe.

Momentan hänge ich auch noch an einem Sketch fest, den ich nicht zum Laufen bekomme (HM-WDS30-OT2-SM). Aber ich bin hartnäckig und geb nicht auf  8) ;D

papa

Zitat von: Tom Major am 18 Februar 2018, 23:47:02
Vielen Dank, jp112sdl, für den link, das hilft mir weiter.

Ich versuche mir ein grundsätzliches Verständnis über den notwendigen code für so einen sketch zu schaffen,
z.B. sowas hier:
DEFREGISTER(Reg1,CREG_AES_ACTIVE,CREG_MSGFORPOS,CREG_EVENTDELAYTIME,CREG_LEDONTIME,CREG_TRANSMITTRYMAX)
...

und viele andere Stellen, gibt es da irgendwo Docs um das zu verstehen?
(außer der Variante, die kompletten sourcen zu lesen und versuchen zu begreifen  :-\)

Tja - da habe ich leider nur eine schlechte Nachricht für Dich. Die Lib nutzt so viel wie möglich von C++ (Vererbung, Templates), C Macros und dem Wissen, wie ein Compiler arbeitet, um auf dem Sketch-Level eine einfache API zu haben. Das bedingt meist aber auch, dass es unterhalb dieser einfachen API recht ordentlich zu Sache geht. Erschwerend kommt noch  hinzu, dass nur begrenzt Resourcen Flash/RAM zur Verfügung stehen, was die Sache nicht unbedingt einfacher macht. Für C++ Anfänger sind die Innereien sicherlich nicht geeignet. Aber ich hoffe, dass auf dem oberen Level, auch eher unerfahrende Entwickler in der Lage sind, die Examples zu verstehen. Da ich immer noch nicht mit allen Sachen so richtig zufrieden bin, lohnt sich eine tiefgreifende Doku auch noch nicht. Ich habe keine Lust/Zeit, ständig die Examples und eine Doku anzupassen. Wobei die Doku ja auch noch erst entstehen muss.

Das oben erwähnte Macro definiert die verfügbaren Register für eine bestimmte Liste und erzeugt eine Klasse mit statischen Funktionen, die dann als Template-Argument in die generische RegisterListen-Klasse kommt und das Mapping zwischen Register-Nummer und relative Position in der Liste im EEProm macht.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

Tom Major

Hallo papa,
Danke für die Info und großen Respekt für Deine Arbeit. Habe mir den code (etwas) näher angeschaut, da steckt wahnsinnig viel Arbeit und know-how drin.
Bin selber u.a. ein C++ Programmierer, aber nicht auf dem Templates Niveau, welches Du betreibst, dazu mache ich das dann doch nicht oft genug.

ZitatAber ich hoffe, dass auf dem oberen Level, auch eher unerfahrende Entwickler in der Lage sind, die Examples zu verstehen.
Da habe ich etwas Zweifel, vielleicht ein rudimentäres Verständnis, aber wenn's ans Nachbauen oder Modifizieren geht, ich glaube da wirst Du ohne Doku mehr oder weniger immer gefragt sein.

Ich habe mich z.B. mit dem HM-SEC-WDS beschäftigt, den ich vielleicht als erstes mal testweise baue weil ich so ein Gerät sowie so anschaffen wollte.
Ich habe auf obersten Level verstanden:
- das Pining vom Arduino (außer den Sensor Pins)
- dass die beiden low Batt Schwellen auf 2,2V und 1,9V gesetzt werden und die Batt jede Stunde gemessen wird.  :)

Ich habe auf obersten Level nicht verstanden, wäre aber m.E. für den Nachbau wichtig:
- wie werden die Pins Sensor Pins 1 und 2 angeschlossen, dass die Zuordnung Dry/Wet korrekt ist?
- Wie ist die Beschaltung der Sensor Pins?
- Wie oft werden die Sensor Pins gemessen?
Ich vermute diese Info wird man auf obersten Level nicht finden und dann z.B. das Messintervall für dieses device in den sourcen zu finden habe ich nicht geschafft..

Danke,
Früher: FHEM 5.x
Jetzt: RaspberryMatic / ioBroker

jp112sdl

Moin!
Ich häng mich mal kurz mit rein... wenn ich falsch liege, möge papa es korrigieren  :)

Soweit ich [bin auch nur Freizeitprogrammierer mit rudimentärsten C(++) Kenntnissen] verstanden habe:

Zitat von: Tom Major am 20 Februar 2018, 01:04:46
- Wie oft werden die Sensor Pins gemessen?
Ich vermute diese Info wird man auf obersten Level nicht finden und dann z.B. das Messintervall für dieses device in den sourcen zu finden habe ich nicht geschafft..

In der ThreeState.h (Master-Branch, Stand: jetzt) Zeile 68:

    // start polling
    set(seconds2ticks(1));


Heißt: Mit jedem Takt werden auch die Pins abgefragt. Nun liegt es an dir - je nachdem was du am 328 angeschlossen hast... 32.768khz, 8MHz, 16MHz, ... - wie oft die Pins abgefragt werden.


Zitat von: Tom Major am 20 Februar 2018, 01:04:46
- wie werden die Pins Sensor Pins 1 und 2 angeschlossen, dass die Zuordnung Dry/Wet korrekt ist?


#define SENS1_PIN 6 //14
#define SENS2_PIN 3 //15

...

msgForPosA(1); // DRY
msgForPosB(3); // WET
msgForPosC(2); // WATER


Das (default)-mapping ist in der ThreeState.h zu finden

  // map pins to pos     00   01   10   11
  uint8_t posmap[4] = {Positions::PosC,Positions::PosC,Positions::PosB,Positions::PosA};


Heißt:






SENS1_PINSENS2_PIN
TrockenHH
FeuchtHL
NassLL
NassLH


Zitat von: Tom Major am 20 Februar 2018, 01:04:46
- Wie ist die Beschaltung der Sensor Pins?

Die Pins werden durch eine (von dir bereit gestellte) externe Schaltung auf H oder L gesetzt.
Es wird hier keine Feuchtigkeit gemessen!

Güßlies,
JP

papa

Zitat von: jp112sdl am 20 Februar 2018, 06:37:26
Moin!
Ich häng mich mal kurz mit rein... wenn ich falsch liege, möge papa es korrigieren  :)

Soweit ich [bin auch nur Freizeitprogrammierer mit rudimentärsten C(++) Kenntnissen] verstanden habe:

In der ThreeState.h (Master-Branch, Stand: jetzt) Zeile 68:

    // start polling
    set(seconds2ticks(1));


Heißt: Mit jedem Takt werden auch die Pins abgefragt. Nun liegt es an dir - je nachdem was du am 328 angeschlossen hast... 32.768khz, 8MHz, 16MHz, ... - wie oft die Pins abgefragt werden.

Nicht ganz. Der ThreeStateChannel ist von Alarm abheleitet. Alarme werden in der Lib genutzt, um Aktionen nach einer bestimmten Zeit auszuführen. Hierzu wird im Alarm die Wartezeit in Ticks (komme ich gleich noch zu) gespeichert und der Alarm einer AlarmClock (sysclock) hinzugefügt. Diese verwaltet beliebig viele Alarme und nutzt einen Timer der CPU zum zählen. Die Auflösung des Timers wind durch das Define TICKS_PER_SECOND (default 100) bestimmt. Damit man nun nicht immer rechnen muss, gibt es die irgendwas2ticks Macros. Der Code oben stetzt also einen Timeout von 1 Sekunde - sprich es wird sekündlich gemessen, da in der trigger Methode, der Alarm wieder reaktiviert wird.
Da der Timer durch die Verwendung der unterschiedlichen Sleep-Modes der ATMega mehr oder weniger ungenau ist, besteht die Möglichkeit einen 32,768kHz Quarz anzuschliessen und die RTC Klasse zu verwenden. Diese nutzt den Timer2 (beim ATMega) und programmiert ihn auf einen Sekundentakt. Dieser Timer ist auch bei Verwendung der Sleep-Modes noch genau. Hier wird dann der Alarm in Sekunden angegeben und es wird rtc anstatt sysclock verwendet.

Zitat von: jp112sdl am 20 Februar 2018, 06:37:26

#define SENS1_PIN 6 //14
#define SENS2_PIN 3 //15

...

msgForPosA(1); // DRY
msgForPosB(3); // WET
msgForPosC(2); // WATER


Das (default)-mapping ist in der ThreeState.h zu finden

  // map pins to pos     00   01   10   11
  uint8_t posmap[4] = {Positions::PosC,Positions::PosC,Positions::PosB,Positions::PosA};


Heißt:






SENS1_PINSENS2_PIN
TrockenHH
FeuchtHL
NassLL
NassLH

Genau das Mapping Pinstatus zu Position ist fest verdrahtet. Die msgForPosX Register bestimmen dann, was wirklich gesendet wird. Das kann dann von außen eingestellt werden.

Zitat von: jp112sdl am 20 Februar 2018, 06:37:26
Die Pins werden durch eine (von dir bereit gestellte) externe Schaltung auf H oder L gesetzt.
Es wird hier keine Feuchtigkeit gemessen!

Die Pins werden nur während der Messung kurz aktiviert - als Input mit PULLUP - ThreeStateChannel::readPin. Zum Auslösen muss also der Pin nach Masse kurz geschlossen werden - z.B. durch Wasser.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

jp112sdl

Ahh, jetzt hab ich das auch verstanden, wie das mit der Taktung funktioniert!

Zitat von: papa am 20 Februar 2018, 08:05:47
Die Pins werden nur während der Messung kurz aktiviert - als Input mit PULLUP - ThreeStateChannel::readPin. Zum Auslösen muss also der Pin nach Masse kurz geschlossen werden - z.B. durch Wasser.
Ich bin da immer skeptisch... ob Wasser eine so hohe Leitfähigkeit hat, um den gepullten Pin runterzuziehen.
Es hängt sicher auch davon ab, wie weit Pin und GND auseinander liegen... aus dem Bauch heraus hätte ich evtl. mit einem Tiny85 analoge Werte gemessen und bei bestimmten Schwellwerten dann digitale Pins entsprechend gesetzt.
Dann könnte man nicht nur erfassen, ob sich der Pin tatsächlich voll im Wasser befindet, sondern auch ob bspw. der Kellerboden durch aufsteigende Nässe aus dem Erdreich den Betonboden durchfeuchtet.

Aber gut... ich schweife vom Thema ab. :)

Ich hab dann aber auch noch eine Frage:
class BatSensor : public BatterySensorUni<17,7,3000> {
  bool m_Extern;
public:
  // sense pin = A3 = 17, activation pin = D7 = 7
  BatSensor () : BatterySensorUni(), m_Extern(false) {}
  virtual ~BatSensor () {}

  void hasStepUp (bool value) {
    m_Extern = value;
    voltage();
  }

  virtual uint8_t voltage () {
    if( m_Extern == true ) {
      return BatterySensorUni<17,7,3000>::voltage();
    }
    return BatterySensor::voltage();
  }
};


Wenn ich diese Klasse in den HM-WDS10-TH-O hole und in
typedef AskSin<LedType, BatterySensorUni,RadioType> BaseHal;
übergebe sowie

    battery.low(22);
    battery.critical(19);
entsprechend wie gehabt mit fixen Werten belege, reicht das dann aus?

Der WeatherChannel hat kein virtual void configChanged () wie der ThreeStateChannel... Ich weiß nicht, ob das wirklich notwendig ist, wenn ich es für mich einfach statisch festlege.

Ich würde auch gern statt des A3 den A7 des Mega328P für die Messung benutzen. Spricht da deiner Meinung nach aus technischer Sicht was dagegen?

Tom Major

Danke an Euch jp112sdl und papa, habe Messintervall und sensor pin mapping verstanden glaub ich und weiß auch jetzt wo ich nachschauen muss (ThreeState.h)

Zitat
// map pins to pos     00   01   10   11
  uint8_t posmap[4] = {Positions::PosC,Positions::PosC,Positions::PosB,Positions::PosA};
Heißt:
SENS1_PIN   SENS2_PIN
Trocken   H   H
Feucht   H   L
Nass   L   L
Nass   L   H

Wenn ich das richtig sehe
uint8_t pinstate = readPin(sens2) << 1 | readPin(sens1);
steht Sensor pin 2 als höherwertiges Bit links, muss dann nicht die Tabelle eigentlich so lauten (z.B. Feucht wäre nicht SENS1_PIN high sondern SENS2_PIN high)

        SENS2_PIN  SENS1_PIN
Nass L    L
Nass L    H
Feucht H    L
Trocken H    H



Ich möchte die Wasserdetektion mit ADC machen, ich habe da letztes Jahr schon Experimente mit einer Spannungsteilerschaltung gemacht und habe Messwerte. Kann ich dafür die Funktion
void trigger (__attribute__ ((unused)) AlarmClock& clock)  {
im Sketch einfach anlegen, dort mein custom ADC handling machen und diese überschreibt dann die originale trigger Funktion in ThreeState.h?
Früher: FHEM 5.x
Jetzt: RaspberryMatic / ioBroker

papa

Zitat von: Tom Major am 20 Februar 2018, 09:59:22
Ich möchte die Wasserdetektion mit ADC machen, ich habe da letztes Jahr schon Experimente mit einer Spannungsteilerschaltung gemacht und habe Messwerte. Kann ich dafür die Funktion
void trigger (__attribute__ ((unused)) AlarmClock& clock)  {
im Sketch einfach anlegen, dort mein custom ADC handling machen und diese überschreibt dann die originale trigger Funktion in ThreeState.h?

Naja - nicht ganz. Du musst eine neue Klasse vom ThreeStateChannel ableiten und dort die trigger Methode überschreiben. Dann kommt diese neue Channelklasse in das ThreeStateDevice-Template.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire

papa

Zitat von: jp112sdl am 20 Februar 2018, 08:39:29
Ich hab dann aber auch noch eine Frage:
class BatSensor : public BatterySensorUni<17,7,3000> {
  bool m_Extern;
public:
  // sense pin = A3 = 17, activation pin = D7 = 7
  BatSensor () : BatterySensorUni(), m_Extern(false) {}
  virtual ~BatSensor () {}

  void hasStepUp (bool value) {
    m_Extern = value;
    voltage();
  }

  virtual uint8_t voltage () {
    if( m_Extern == true ) {
      return BatterySensorUni<17,7,3000>::voltage();
    }
    return BatterySensor::voltage();
  }
};


Wenn ich diese Klasse in den HM-WDS10-TH-O hole und in
typedef AskSin<LedType, BatterySensorUni,RadioType> BaseHal;
übergebe sowie

    battery.low(22);
    battery.critical(19);
entsprechend wie gehabt mit fixen Werten belege, reicht das dann aus?

Der WeatherChannel hat kein virtual void configChanged () wie der ThreeStateChannel... Ich weiß nicht, ob das wirklich notwendig ist, wenn ich es für mich einfach statisch festlege.

Ich würde auch gern statt des A3 den A7 des Mega328P für die Messung benutzen. Spricht da deiner Meinung nach aus technischer Sicht was dagegen?

Eigentlich brauchts Du diese Klasse gar nicht. Sie ist dafür gemacht worden, um im HM-Sec-RHS sowohl Hardware mit und ohne Stepup-Wandler verwenden zu können. Die Lib kennt unterschiedliche Implementierung für die Batteriemessung (siehe BatterySensor.h):

NoBattery - keine Funktion, einfach leer, bei Netzversorgung
BatterySensor - interne Spannungsmessung des ATMega, bei Betrieb ohne Stepup
BatterySensorUni - Messungs über Spannungsteiler und AD-Wandler, für Stepup, kompatibel zur UniversalSensor von Dirk
BatterySensorExt - Messungs über Spannungsteiler und AD-Wandler, für Stepup, https://github.com/rlogiacco/BatterySense

Je nachdem wie Deine Hardware aussieht, wird die entsprechende Klasse in das HAL-Template gesteckt. Du kannst natürlich auch andere Pins verwenden. Dann muss Deine Hardware auch entsprechend aufgebaut sein.

configChanged() ist in der Channel-Klasse leer implementiert und kann einfach überschrieben werden. Es braucht nicht virtual zu sein, da der Aufruf über die im Device-Template angegebene Klasse erfolgt.

Da virtuelle Methoden auf dem 8-bit AVR sehr teuer sind, habe ich versucht diese wo immer möglich zu vermeiden.
BananaPi + CUL868 + CUL433 + HM-UART + 1Wire