1-Wire-Slave-Baukasten V.2

    • 1-Wire-Slave-Baukasten V.2

      1. Grundsätzliches

      Nachdem meine Homepage abgeschaltet worden ist,
      habe ich meine Erkenntnisse dem "bascom-forum" (mit Bindestrich) anbefohlen,
      wo sie nun anscheinend auch wieder im Nichts verschwunden sind.
      Deswegen versuche ich es hier nochmal - hoffentlich mit mehr Erfolg.

      Worum geht es dabei?

      1-Wire ist eine pfiffige Technik bzw. ein Bussystem von Dallas/Maxim,
      die Daten über größere Entfernungen über 2 (Data und GND) bzw. 3 Leitungen (Data, GND, VCC) transportieren kann.
      -> 1wire

      Da gibt es so wunderbare Bausteine wie
      - den DS18B20 Temperatursensor
      - den DS2438 Batteriemonitor
      - den DS2423 2x32-Bit-Counter
      - den DS2450 4x16-Bit-AD-Wandler
      - den DS2408 und DS2413 8xPIO bzw. 2xPIO
      (Es gab (oder gibt?) sogar eine ganze Wetterstation, die nur mit 1-Wire-Bausteinen betrieben wird/wurde)

      Leider, ja leider, gibt es nicht für alle Bereiche fertige Sensoren
      und manche Bausteine wurden abgekündigt (DS2423, DS2450).

      Deswegen finden sich im Internet einige Ansätze,
      vorhandene Bausteine durch den Einsatz von Mikrocontrollern nachzubauen oder neue zu entwickeln.
      Hier einige gute Beispiele:
      -> mikrocontroller.net/topic/241934#new
      -> mikrocontroller.net/topic/44100
      (vor allem DS2423)
      -> mikrocontroller.net/topic/271772
      (DCF77)
      -> tm3d.de/index.php/1-wire-device-mit-avr
      (DS18B20, DS2423, Barometer)
      -> mcselec.com/index.php?option=c…ask=view&id=256&Itemid=57
      (DS2450 mit BASCOM)
      -> brain4home.eu/index.php

      Nachdem ich diese Vorlagen einige Zeit studiert und langsam auch etwas begriffen habe,
      kam mir der Gedanke, daraus einen einfachen 1-Wire-Slave-Baukasten zu entwickeln,
      mit dem man unter BASCOM leicht eigene Slaves erstellen kann.
      Auf diese Weise kann man einerseits evtl. abgekündigte Bausteine begrenzt nachbilden,
      aber vor allem andere Sensoren (z.B. analoge oder I²C) in das 1-Wire-System einbinden.
      Dies ist z.B. bei dem weit verbreiteten SHT11 durchaus sinnvoll.

      Schwierig ist das jedoch, WIE diese neuen Slaves vom Master angesprochen werden sollen,
      wenn der Master bzw. dessen Steuersoftware diesen Slavetyp überhaupt nicht kennt!
      Es gibt zwei Lösungswege:
      - Wenn man die Steuersoftware selbst schreiben kann (z.B. eben in BASCOM),
      ist ein eigener Family-Code am einfachsten.
      Dann kann man darüber den Slave eindeutig identifizieren und ihn seiner Funktion entsprechend auslesen.
      - Wenn man auf eine fertige Steuersoftware zurückgreifen will/muss,
      bleibt einem nichts anderes übrig, als den Slave so zu programmieren,
      dass er sich analog zu einem vorhandenen Baustein verhält.
      Die Gefahr, dass es dabei zu Doppelungen in der 64-Bit-ID kommt,
      ist dabei sicher gering, aber trotzdem möglich.

      Jetzt muss man noch ein paar Infos dazwischenschieben:
      Jeder Baustein ist vom Hersteller mit einer eindeutigen ID versehen worden
      und kann darüber vom Master angesprochen werden.
      Diese umfasst 8 Bytes bzw. 64 Bits.
      Das 1. Byte steht dabei für den "Familiy-Code" und gibt Auskunft über die Funktion des Bausteins (z.B. &H28 -> DS18B20).
      Das letzte Byte ist eine CRC8-Prüfsumme der vorangehenden 7 Bytes

      Meine 1-Wire-Slave-Lösung:
      - In der Slave-Software ist ein DS18B20 als Standard eingestellt
      (Data &H28 , &H53 , &H48 , &H54 , &H00 , &H00 , &H00 , &H68).
      - Um eine andere ID mit evtl. einem anderen Familiy-Code einzustellen,
      muss man diese in die ersten 8 Bytes des EEPROMs des ATmega/ATtinys schreiben.
      Dann wird diese automatisch beim Starten als (neue) ID genutzt.
      - Der Slave verhält sich ähnlich wie ein DS18B20,
      d.h. der Befehl "&H44" (Convert Temperature) berechnet alle Werte,
      schreibt sie in die ersten 8 Bytes eines Arrays
      und erstellt daraus eine CRC8-Prüsumme,
      die in das 9.Byte des Arrays geschrieben wird.
      Der Befehl "&HBE" (Read Scatchpad) gibt 8 Werte und die CRC-Prüfsumme (=9. Wert) aus.
      - Diese 8 Werte selbst sind aber nicht mit denen eines DS18B20 kompatibel,
      sondern daraus muss man nun, je nach Funktionen des Slaves, seine Werte gewinnen.
      Das funktioniert also nur mit Steuerssoftware,
      die auch das Scatchpad ausgibt und nicht nur fertige Werte anzeigt.
      Möglich ist das z.B. mit DigiTemp oder den 1-Wire-Kernel-Modulen des RaspberryPi,
      leider geht es wohl nicht mit owfs oder IPSymcon.
      Wenn man auf eigene Software zurückgreifen kann,
      dann kann man für den Slave entweder einen eigenen Family-Code wählen (z.B. &HFE)
      oder über den Befehl "&H10" und "1wread()" einen Wert auslesen.
      Ist er <> 255/&HFF, dann ist es kein echter DS18B20.
      (Eine eigene 64-Bit-ID(s.o.) kann man sich z.B. bei
      -> tm3d.de/index.php/tools
      berechnen lassen.)

      Nochmal zur Sicherheit:
      Im Gensatz zur ID (s.o.) besteht das Scatchpad aus 9 Bytes:
      8 Datenbytes und ein 9. CRC8-Byte (aus den 8 Datenbytes).
      Über dieses Scatchpad tauschen mehrere Bausteine Daten mit dem Master aus.
      (Bitte nicht verwechseln)

      Soweit mal die Grundinfos.
      Der Rest (Code) kommt bald.

      Liebe Grüße,
      RoBue

      Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von RoBue ()

    • Dann hoffen wir mal das Beste ...

      2. Der Code des 1-Wire-Slave-Baukastens

      "Baukasten" das meint,
      der User kann auf einen lauffähigen Code als Gerüst zurückgreifen,
      in den er einfach an bestimmten Stellen seine Anwendungen einfügt,
      ohne dass er unbedingt begreifen muss,
      was da eigentlich abgeht (das Meiste ist in Assembler geschrieben!)

      Das Prinzip der 1-Wire-Slaves mit Bascom ist recht simpel und trotzdem genial:
      Der 1-Wire-Eingang wird einfach (mit Assemblerroutinen) abgepollt.
      Dies geschieht so lange, bis der Bus auf 0/low gezogen wird.
      Dann wird mit Hilfe von Timer0 oder Timer1 (= RoBue V.2) die Dauer dieses Vorgangs abgefragt,
      um festzustellen, was der Master nun eingentlich will bzw. ob der Master überhaupt verantwortlich ist.
      Wenn der Master tatsächlich etwas geschickt hat,
      wird in die einzelnen Funktionen verzweigt.
      Das Trickreiche an dem Ganzen ist,
      dass der Timer-Interrupt keine Register rettet ("nosave"),
      weil dazu keine Zeit zur Verfügung steht.
      Deswegen wird die Isr-Routine nicht wirklich mit einem "Return" verlassen,
      sondern mit "Goto".
      Darum muss man zwingend den Stackpointer zurücksetzen,
      sonst stürtzt das Progamm nach einiger Zeit ab.

      BASCOM-Quellcode

      1. ' RoBue:
      2. ' Der Stackpointer liegt an der Obergrenze des SRAM
      3. '
      4. ' - SRAM bei ATtiny25: &H5F + &H80 = &HDF
      5. ' Const Stackpointer_low = &HDF
      6. ' (nur 1 Wert fuer Stackpointer !!!)
      7. ' - SRAM bei ATtiny45: &H5F + &H100 = &H15F
      8. Const Stackpointer_high = &H01
      9. Const Stackpointer_low = &H5F
      10. ' - SRAM bei ATtiny85: &H5F + &H200 = &H25F
      11. ' Const Stackpointer_high = &H02
      12. ' Const Stackpointer_low = &H5F
      13. ' ...
      14. ' *********************** isr
      15. Isr:
      16. ' Das ist Strange mit den Goto aus der Isr rauszugehen.
      17. ' aber es läuft ...
      18. ' RoBue: ... doch nicht wirklich!
      19. ' Der Stackpointer muss zurueckgesetzt werden !!!
      20. Spl = Stackpointer_low
      21. Sph = Stackpointer_high
      22. If Dq = 0 Then
      23. Timer_t1 = T1reset
      24. Goto Rwaitrise
      25. Else
      26. Goto Waitreset
      27. End If
      28. Return
      Alles anzeigen



      Im Grunde muss man nun nur an 2 Stellen in den Baukasten-Code etwas einfügen:

      1. Im Bereich "Variable und Init-Routinen"
      Da muss alles rein,
      was zur Initialisierung der eigenen Hardware nötig ist
      und was man als zusätzliche Variablen braucht.

      BASCOM-Quellcode

      1. ' *********************** TIMER1 and ISR
      2. ' TIMER1 fuer 1-Wire-Kommunikation
      3. Config Timer1 = Timer , Prescale = 64
      4. ' Stop Timer1
      5. Tccr1 = Tccr1 And &B11110000
      6. Enable Timer1
      7. On Timer1 Isr Nosave
      8. Timer_t1 Alias Tcnt1
      9. '***************************************
      10. ' Variable und Init-Routinen
      11. ' ***************************************
      12. ' Start -> 4x Blinken der LED
      13. For I = 1 To 4
      14. Match_led = 1
      15. Waitms 250
      16. Match_led = 0
      17. Waitms 250
      18. Next I
      19. ' Hauptschleife
      Alles anzeigen

      2. Im Bereich "Calculatedata"
      Dort werden z.B. die Messwerte berechnet
      und dann in das "Daten_array" (= Scratchpad) geschrieben.
      Natürlich kann man dies auch mit Gosubs und Includes etwas übersichtlicher machen.

      BASCOM-Quellcode

      1. ' RoBue: Erzeuge Daten
      2. ' -------------------------------
      3. '
      4. ' Berechnen der Werte, die dann ins "Daten-array" geschrieben werden.
      5. Calculatedata:
      6. If Match_slave = 1 Then
      7. ' Status auf 0 -> alles o.k.
      8. Daten_array(8) = 0
      9. ' **********************
      10. ' * Gosub Berechnungen *
      11. ' **********************
      12. Daten_array(9) = Crc8(daten_array(1) , 8)
      13. End If
      14. 'Goto Readb
      15. Goto Waitreset
      Alles anzeigen
      Das klingt nun immer noch etwas theoretisch,
      aber praktische Beispiele folgen demnächst.

      Hier mal die Vorlage für ATtinys 25-45-85.
      Der Code ist ziemlich ausführlich kommentiert.
      Wichtig ist, dass man die Stackpointer für den jeweiligen ATtiny richtig einstellt!!!

      1-Wire-Slave_ATtiny25-45-85_Timer1_Vorlage.zip

      LG RoBue

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von RoBue ()

    • Jetzetle wollen wir mal ein erstes praktisches Beispiel in Angriff nehmen:

      3. Ein 1-Wire-32-Bit-Counter

      Da der DS2423 kaum mehr zu bekommen ist,
      wäre ein Ersatz dafür sicher sinnvoll.
      Es gibt auch schon Emulationen dafür.
      Leider ist sein Protokoll nicht ohne.
      Darum habe ich mich zu einer ganz einfache Lösung entschlossen:
      Vergiss die Kompatibilität, mach einfach einen eigenen.

      Gut - aber wie?

      Nun hat ein ATtiny einen Timer, der auch als Counter eingesetzt werden kann:
      Timer0/Counter0 am PortB.2.
      Solche Hardware-Counter haben den Vorteil,
      dass sie automatisch und unabhängig vom eigentlichen Programm ablaufen (können).
      Man muss sie nur rechtzeitig auslesen,
      bevor sie "überlaufen".

      Aber jetzt kommt leider das erste Problem:
      Beim ATtiny25-45-85 nur einen Timer als Counter nutzen: Timer0
      und der wird ja in der Regel für die 1-Wire-Kommunikation gebraucht.
      Also habe ich den Code so umgeschrieben,
      dass die 1-Wire-Kommunikation über Timer1 läuft.
      Darum trägt der Baukasten übrigens den Zusatz: V.2 (d.h. Version 2)
      Zumindest in älteren Bascom-Versionen gibt es da einen Bug.
      Deshalb muss man diesen Timer manuell einstellen!
      (Vielleicht ist der Bug inzwischen behoben)

      BASCOM-Quellcode

      1. ' *********************** TIMER1 and ISR
      2. ' TIMER1 fuer 1-Wire-Kommunikation
      3. Config Timer1 = Timer , Prescale = 64
      4. ' Stop Timer1
      5. Tccr1 = Tccr1 And &B11110000
      6. Enable Timer1
      7. On Timer1 Isr Nosave
      8. Timer_t1 Alias Tcnt1
      9. '***************************************
      Alles anzeigen

      Damit wird Timer0 frei und kann als Counter genutzt werden.

      Soweit so gut.

      Jetzt kommt das 2. Problem:
      Leider kann man aber nur 256 Impulse zählen (8 Bit), bis ein Überlauf eintritt.
      Wenn man den mit einbezieht, dann sind sogar 511 Impulse möglich,
      bevor das Ganze nicht mehr eindeutig ist.

      Wie kommt man nun aber auf 32 Bit?

      Immer wenn der Slave vom Master aufgerufen wird
      (bei mir ist das z.B. 1 mal in der Minute),
      wird der Counter und dessen Überlaufregister ausgelesen
      und zu einer 32-Bit-Variablen (DWORD) hinzugezählt.
      Dann wird Counter und Überlaufregister gelöscht
      und es ist wieder Platz für bis zu 511 Impulse.
      Nicht optimal, aber für viele Fälle völlig ausreichend.
      Man muss eben oft genug den Slave aufrufen.

      Also fügt man in den Baukasten-Code im Init-Teil (s.o.) folgenden Code ein:

      BASCOM-Quellcode

      1. ' ***************************************************************************
      2. ' * TIMER0 als Counter *
      3. ' ***************************************************************************
      4. ' Variablen fuer Counter
      5. Dim Counterwert As Dword
      6. Dim Counter_1 As Byte At Counterwert Overlay
      7. Dim Counter_2 As Byte At Counterwert + 1 Overlay
      8. Dim Counter_3 As Byte At Counterwert + 2 Overlay
      9. Dim Counter_4 As Byte At Counterwert + 3 Overlay
      10. ' TIMER0 als Counter an PORTB.2
      11. Config Timer0 = Counter , Edge = Falling
      12. Config Pinb.2 = Input
      13. ' Pullup ein
      14. Portb.2 = 1
      15. ' Und los gehts ...
      16. Start Timer0
      Alles anzeigen
      "Calculatedata" sieht nun so aus:

      BASCOM-Quellcode

      1. ' RoBue: Erzeuge Daten
      2. ' -------------------------------
      3. '
      4. ' Berechnen der Werte, die dann ins "Daten-array" geschrieben werden.
      5. Calculatedata:
      6. If Match_slave = 1 Then
      7. ' Status auf 0 -> alles o.k.
      8. Daten_array(8) = 0
      9. ' Ueberlauf auslesen
      10. Daten_array(6) = Tifr.1
      11. ' und zuruecksetzen
      12. Set Tifr.1
      13. Set Tifr.4
      14. ' 8-Bit-Counter auslesen,
      15. Daten_array(5) = Tcnt0
      16. ' und Counter zuruecksetzen
      17. Tcnt0 = 0
      18. ' Werte zur 32-Bit-Variable addieren
      19. Counterwert = Counterwert + Daten_array(5)
      20. If Daten_array(6) = 1 Then
      21. Counterwert = Counterwert + 256
      22. End If
      23. ' 32-Bit-Counterwert in Scratchpad schreiben,
      24. Daten_array(1) = Counter_1
      25. Daten_array(2) = Counter_2
      26. Daten_array(3) = Counter_3
      27. Daten_array(4) = Counter_4
      28. Daten_array(9) = Crc8(daten_array(1) , 8)
      29. End If
      30. 'Goto Readb
      31. Goto Waitreset
      Alles anzeigen
      Beim Auslesen des Scratchpads (s.o.) erhält man nun folgende Werte:
      Wert 1-4 -> 32-Bit Counter (Wert1 + 256*Wert2 + 65535*Wert3 + 16777216*Wert4)
      Wert 5,6 -> 9-Bit Differenz-Counter (Counter und Überlauf)
      Wert 7 -> leer (evtl. Messung Versorgungsspannung)
      Wert 8 -> Fehlerausgabe
      Wert 9 -> CRC8

      Zum Auslesen des Scratchpads siehe Beitrag von Michael:
      DS1820 DS18S20 DS18B20 Temperatursensor 1Wire

      Im Code sind zwei Möglichkeiten als ID vorgesehen:
      Einmal als DS18B20 mit Familiy-Code "&H28",
      zum andern als neuer Bausteintyp mit dem Family-Code "&HFD" (bisher ungenutzt).

      BASCOM-Quellcode

      1. ' RoBue:
      2. ' ID fuer 1-Wire-Baustein (&H43 steht fuer "C" wie Counter)
      3. Id:
      4. '
      5. ' DS18B20-Familiy (&H28)
      6. ' Data &H28 , &H43 , &00 , &H00 , &H00 , &H00 , &H01 , &H6C
      7. '
      8. ' oder eigene Family: (&HFD)
      9. Data &HFD , &H43 , &H00 , &H00 , &H00 , &H00 , &H01 , &H0E

      Anschlussbelegung des ATtiny:
      Pin 1 und 8: VCC
      Pin 2 und 3: unbelegt
      Pin 4: GND
      Pin 5: Kontroll-LED (gegen GND)
      Pin 6: 1-Wire-Port
      Pin 7: Counter-Eingang mit Kondensator (z.B. 10nF) gegen GND


      1-Wire-Slave-0xFD_ATtiny25_Counter_Timer1.bas

      LG RoBue

      Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von RoBue ()

    • Schieben wir gleich den nächsten Baustein nach:

      4. Ein 1-Wire-Slave mit SHT11 für Temperatur und Feuchte

      Das Prinzip ist das Gleiche wie beim Counter,
      nur dass der Code nicht mehr in einen ATtiny25 passt,
      sondern man mindestens einen ATtiny45 braucht.
      Ich benutze die Routinen aus dem Bascom-Sample von Stuart Leslie,
      die ich in einen Initialisierungs- und einen Berechnungsteil aufgesplittet habe.

      Leider braucht der SHT11 mindestens 300ms zur Berechnung,
      d.h. nachdem der Master den Befehl "&H44" gesendet hat,
      ist der der Slave für diese Zeit nicht mehr ansprechbar.

      Beim Auslesen des Scratchpads (s.o.) erhält man nun folgende Werte:
      Wert 1,2 -> Temperatur = (Wert1 + Wert2*256)/10
      Wert 3,4 -> Luftfeuchte = (Wert3 + Wert4*256)/10
      Wert 5,6 -> 9-Bit Differenz-Counter (Counter und Überlauf)
      Wert 7 -> leer (evtl. Messung Versorgungsspannung)
      Wert 8 -> Fehlerausgabe
      Wert 9 -> CRC8

      Im Code sind zwei Möglichkeiten als ID vorgesehen:
      Einmal als DS18B20 mit Familiy-Code "&H28",
      zum andern als neuer Bausteintyp mit dem Family-Code "&HFE" (bisher ungenutzt).

      Anschlussbelegung des ATtiny:
      Pin 1 und 8: VCC
      Pin 2: SHT11 - Sck (Pullup 10k gegen VCC)
      Pin 3: SHT11 - Dta (Pullup 10K gegen VCC)
      Pin 4: GND
      Pin 5: Kontroll-LED (gegen GND)
      Pin 6: 1-Wire-Port
      Pin 7: Counter-Eingang mit Kondensator (z.B. 10nF) gegen GND

      1-Wire-Slave-0xFE_ATtiny45_SHT11_Counter_Timer1.bas

      Fortsetzung folgt demnächst,
      RoBue

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von RoBue ()

    • Und weiter gehts:

      5. 1-Wire-Slaves mit BMP085/180 und BME280

      Für Wetterüberwachung ist das Messen des Luftdrucks obligatorisch.

      Dazu gibt es von Bosch 2 Sensoren mit i2c-Anschluss:
      - BMP085 und sein Nachfolger BMP180 (inzwischen sogar 280),
      der Temperatur und Luftdruck misst.
      - BME280,
      der neben Temperatur und Luftdruck auch die Luftfeuchte misst.

      Beide Sensoren gibt es inzwischen auf Breakoutboards.

      Für beide wurden Routinen in Bascom geschrieben,
      - für den BMP z.B. von MAK3 (altes Forum),
      - für den BME von nightflyer88 (-> mikrocontroller.net/topic/384287).
      Herzlichen Dank dafür.

      Auch diesmal habe ich mich als "Programmierschmarotzer" betätigt
      und im Großen und Ganzen nur deren Code für den Einsatz als 1-Wire-Slave umgeschrieben.

      Im Unterscheid zu den vorigen Beispielen werden die Routinen als Include-Files eingebunden.

      Außerdem erfolgt beim Programmstart eine Prüfung, ob der Sensor überhaupt vorhanden ist.
      Wenn er nicht erkannt wird, blinkt die Kontroll-LED dauernd.

      Der Code ist jeweils so lang, dass man nun auf jeden Fall einen ATtiny85 braucht.

      Beim Auslesen des Scratchpads (s.o.) erhält man nun folgende Werte:
      Wert 1,2 BME/BMP: Temperatur = (Wert1 + Wert2*256)/10 in °C
      Wert 3,4 BME: Luftfeuchte = (Wert3 + Wert4*256)/10 in % / BMP: unbenutzt
      Wert 5,6 BME/BMP: Luftdruck = (Wert5 + Wert6*256)/10 in hPa
      Wert 7 leer (evtl. Messung Versorgungsspannung)
      Wert 8 Fehlerausgabe
      Wert 9 CRC8

      Anmerkung:
      Der ausgegebene Luftdruck ist der temperaturbereinigte absolute Luftdruck am Messort.
      Zum Vergleich muss er noch in den relativen umgerechnet werden ("Barometrische Höhenformel").

      Anschlussbelegung des ATtiny85:
      Pin 1 und 8: VCC --- Längsregler 3,3V ------- Sensor VCC
      Pin 2: ---------------- Pegelwandler 3,3V ----- Sensor SCL
      Pin 3: ---------------- Pegelwandler 3,3V ----- Sensor SDA
      Pin 4: GND -------------------------------------- Sensor GND
      Pin 5: Kontroll-LED (gegen GND)
      Pin 6: 1-Wire-Port
      Pin 7: unbelegt

      Da beide Sensoren nur für max. 3,3V ausgelegt sind,
      braucht man theoretisch zwischen dem ATtiny und dem Sensor einen Pegelwandler.
      Diese kannm an günstig als fertige Platinchen kaufen
      und sie enthalten auch die nötigen Pullups (auf beiden Seiten).


      - Code für den BMP085/180: 1-Wire-Slave_BMP.zip

      - Code für den BME280: 1-Wire_BME.zip

      Hier noch ein Bild von meinem 1-Wire-Wetter-Modul (BME) mit Pegelwandler auf Lochraster.

      1-Wire-Slave_Wettermodul_Text.jpg

      Noch eine Anmerkung zu der Messgenauigkeit:
      Trotz einer Unmenge an Kalibrierungsdaten und einer theoretischen Genauigkeit < 1Pa,
      weichen die Dinger untereinander doch mehrere hPa voneinander ab.
      Man muss also neben der Umrechnung von absolutem Luftdruck in den relativen immer auch noch einen grundsätzlichen Offset mit vorsehen, den man durch den Vergleich mit umliegenden Wetterstationen gewinnen muss.

      LG RoBue

      Dieser Beitrag wurde bereits 14 mal editiert, zuletzt von RoBue ()

    • 6. Zwischenbemerkung:

      1-Wire-Slaves mit 3,3V-Sensoren


      Viele Sensoren sind inzwischen nur auf 3,3V ausgelegt
      und sind nicht 5V-tolerant, d.h. sie werden beim Betrieb mit 5V zerstört.
      Dazu gehören z.B. die BMP- und BME-Sensoren (s.o.)

      Da aber der 1-Wire Bus mit ca. 5V vetrieben werden sollte,
      muss man sich überlegen, wie man 3,3V und %V zusammenbringt.

      Ich habe drei Varianten getestet:

      a) Der Klassiker: Pegelwandler zwischen AVR und Sensor

      Diese gibt es als kleine, fertige Platinchen zu kaufen.
      Ein Längsregler wandelt die 5V in 3,3V um.
      2 FETS machen passen die Leitungen (SCL und SDA) an.
      Die Pullups sind auf beiden Seiten schon integriert.

      Wettermodul_BMP085_HIH6131.jpgPegelwandler.jpg

      b) Der Sparsame: Pegelwandler zwischen AVR und 1-Wire-Bus

      Man betreibt den AVR mit 3,3V
      und verbindet den Sensor direkt mit ihm.
      Dazu muss man mit einen Spannungsregler (z.B. 78L33) die Betriebsspannung auf 3,3V verringern.
      Jetzt wird nur der 1-Wire-Port des AVR über einen FET auf 5V hochge-"shiftet".

      1-Wire-Slave_Pegelwandler.jpg

      c) Die Notlösung (?): 3,3V Betrieb direkt an 1-Wire

      Da der AVR mit 5V und 3,3V arbeitet, kam mir die Idee:
      Wie wäre es, wenn man den AVR mit 3,3V betreibet (Spannungsregler, s.o.)
      und den 1-Wire-Port DIREKT mit dem 1-Wire-Bus verbindet:
      Und siehe da: Es scheint auch zu funktionieren.

      LG RoBue
    • 7. Zwischenbemerkung 2:
      Berechnung von absoluter Luftfeuchte und Taupunkt


      Manchmal braucht man nicht nur die relative,
      sondern die absulute Luftfeuchte oder auch den Taupunkt.
      Nach einigem Suchen bin ich auf einige Beispiele gestoßen,
      die ich in folgenden Code zusammengefasst habe:

      BASCOM-Quellcode

      1. '**********************************************************
      2. 'Compiler : BasCom
      3. 'Hardware : AVR-Ctrl / RoBue AVR-PC-Control
      4. ' : LCD, DS1307, ...
      5. 'Chip type : ATmega644P
      6. 'Clock frequency : 8,000000 MHz
      7. '**********************************************************
      8. ' Routinen zur Berechnung von Werten aus Temperatur und Luftfeuchte
      9. $regfile = "m644pdef.dat"
      10. $crystal = 8000000
      11. ' framesize
      12. ' - fuer Prozeduren
      13. ' - Umwandlung von Variablen in andere Datentypen
      14. $framesize = 128
      15. ' hwstack:
      16. ' - 32 Bytes fuer Interrupts
      17. ' - 2 pro Gosub
      18. $hwstack = 64
      19. ' swstack:
      20. ' - fuer Prozeduren
      21. $swstack = 32
      22. $baud = 9600
      23. ' Gemeinsame Variable fuer Ausgabe
      24. Dim Ausgabehilfswert As Single
      25. Dim A_feuchte As Single
      26. Dim A_temperatur As Single
      27. Dim Tp As Single
      28. Dim Sdd As Single
      29. Dim Dd As Single
      30. Dim Fa As Single
      31. Do
      32. ' Eingabewerte (Beispiel):
      33. A_temperatur = 28.5
      34. A_feuchte = 63.7
      35. Gosub Meteowerte
      36. If Tp = 9999 Then
      37. Print "Error"
      38. Else
      39. Print "Temperatur: " ; A_temperatur ; " °C"
      40. Print "Luftfeuchte " ; A_feuchte ; " %H"
      41. Print "Saettigungsdd: " ; Sdd ; " hPa"
      42. Print "Dampfdruck: " ; Dd ; " hPa"
      43. Print "Feuchtegehalt: " ; Fa ; " g/m³"
      44. Print "Taupunkt: " ; Tp ; " °C"
      45. End If
      46. Print
      47. Wait 15
      48. Loop
      49. End
      50. Meteowerte:
      51. ' Infos: -> http://www.wetterochs.de/wetter/feuchte.html
      52. ' Berechnung nur fuer Werte ueber 0°C
      53. If A_temperatur >= 0 Then
      54. ' - Saettigungsdampfdruck (o.k.):
      55. ' Sdd = 6.1078 * 10^ ((7.45 * Temperatur) / (237.3 + Temperatur))
      56. Ausgabehilfswert = A_temperatur
      57. Ausgabehilfswert = 237.3 + Ausgabehilfswert
      58. Ausgabehilfswert = 7.5 / Ausgabehilfswert
      59. Ausgabehilfswert = Ausgabehilfswert * A_temperatur
      60. Ausgabehilfswert = 10 ^ Ausgabehilfswert
      61. Sdd = Ausgabehilfswert * 6.1078
      62. ' Dampfdruck
      63. ' Dd = Feuchte / 100 * Sdd
      64. Ausgabehilfswert = A_feuchte * Sdd
      65. ' Ausgabehilfswert = Ausgabehilfswert / 100
      66. ' (Wert auch noch durch 10 teilen s.o => 1000
      67. Dd = Ausgabehilfswert / 100
      68. ' Feuchtegehalt / absolute Luftfeuchte(o.k.):
      69. ' Fa = 216.7 * Dd / (237.3 + Temperatur)
      70. Ausgabehilfswert = 273.15 + A_temperatur
      71. Fa = 216.7 * Dd
      72. Fa = Fa / Ausgabehilfswert
      73. ' Taupunkt (o.k.):
      74. Ausgabehilfswert = Dd / 6.1078
      75. Ausgabehilfswert = Log10(ausgabehilfswert)
      76. Tp = 7.5 - Ausgabehilfswert
      77. Tp = 237.3 / Tp
      78. Tp = Tp * Ausgabehilfswert
      79. Else
      80. ' Errorausgabe
      81. Tp = 9999
      82. End If
      83. Return
      Alles anzeigen

      LG RoBue

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von RoBue ()

    • So, jetzt kommt der vorerst letzte Streich:

      8. 1-Wire-Slave mit ATmega8 und LCD

      Dieses Projekt stellt ein Vorstadium des Slavebaukastens dar.
      Hier ging es mir darum, eine Art Terminal mit LCD zu erstellen.
      Weil man dafür mehr Ports braucht, ist ein ATmega8 eine gute Wahl.
      Wenn der Slave zum Berechnen der Werte aufgefordert wird,
      werden diese auch ins LCD geschrieben.
      Die 2x8-Zeichen LCDs von Pollin eigneten sich dazu optimal.
      Leider gibts die nicht mehr :(

      Ich hab so ein Ding als Kontrolle in unserem Gewölbekeller.

      Beim Auslesen des Scratchpads (s.o.) erhält man nun folgende Werte:
      Wert 1,2 -> Temperatur = (Wert1 + Wert2*256)/10
      Wert 3,4 -> Luftfeuchte = (Wert3 + Wert4*256)/10
      Wert 5,6 -> 16-Bit-Counter / AD-Messwert (z.B. Fotodiode) / leer
      Wert 7 -> leer (evtl. Messung Versorgungsspannung)
      Wert 8 -> Fehlerausgabe
      Wert 9 -> CRC8

      Schaltplan ist im ZIP-File

      1-Wire-Slave_ATmega8_SHT11_LCD.jpg

      1-Wire-Slave_ATmega8_SHT-LCD.zip

      Soweit mal meine Entwicklungen zum Thema 1-Wire-Slave.

      Über Rückmeldungen würde ich mich natürlich freuen.

      Vielleicht können wir noch weitere Sensoren auf diese Weise in den 1-Wire-Bus integrieren.
      Macht mal Vorschläge - und ich schlage dann zurück ;)

      Ich werde demnächst mal einige Routinen zum Thema 1-Wire-Master im Forum zum Besten geben,
      damit man die Slaves auch nutzen kann.

      Viel Spaß,
      RoBue

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von RoBue ()

    • 9. 1-Wire-Slave mit MAX6675 (0 - 1024°C)

      Nachdem sk8erboi den Code zum Auslesen des MAX6675 hier eingestellt hat
      -> MAX6675 Typ-K Temperatur
      und mir freundlicherweise einen mit Temperaturfühler zugeschickt hat
      (Herzlichen Dank für beides!)
      habe ich das gleich für den 1-Wire-Slave-Baukasten umgestrickt.

      Da ein DS18B20 max. bis 125°C messen kann,
      eignet er sich für bestimmte Funktionen, z.B. Brennerüberwachung nicht.
      Da ist der MAX6675 in Kombination mit einem Temperaturfühler Typ-K mit bis zu 1024°C eine echte Altternative.

      Man braucht mindestens einen ATtiny45.
      Ich vermute mal, dass das "Shiftin" ziemliche Code-Intensiv ist.

      In den "Init"-Bereich kommt:

      BASCOM-Quellcode

      1. '***************************************
      2. '***************************************
      3. ' MAX6675:
      4. ' CS -----> PORTB.2
      5. ' SCK -----> PORTB.4
      6. ' SOut -----> PORTB.3 (bzw. PINB.3)
      7. Cs Alias Portb.2
      8. Config Cs = Output
      9. Sck Alias Portb.4
      10. Config Sck = Output
      11. So Alias Pinb.3
      12. Config So = Input
      13. ' Variable
      14. Dim Temp As Word
      15. Dim Tempx As Single
      16. Dim Erstmessung As Byte
      17. ' Messung schon mal starten
      18. Cs = 1
      19. ' ****************************************
      Alles anzeigen


      In "Calculatedata" schreibt man:

      BASCOM-Quellcode

      1. Calculatedata:
      2. If Match_slave = 1 Then
      3. ' Status auf 0 -> alles o.k.
      4. Daten_array(8) = 0
      5. ' MAX6675 auslesen:
      6. Temp = 0
      7. ' - Konversion stoppen
      8. Cs = 0
      9. Waitms 1
      10. ' - Daten auslesen
      11. Shiftin So , Sck , Temp , 0 , 16 , 10
      12. ' - Konversion (Messung) wieder starten
      13. Cs = 1
      14. ' Rechnen
      15. Shift Temp , Right , 3
      16. Tempx = Temp * 0.25
      17. Tempx = Tempx - 1
      18. ' 1 Nachkommastelle
      19. Tempx = Tempx * 10
      20. Temp = Round(tempx)
      21. ' Werte in Ausagbe-Array eintragen
      22. If Erstmessung = 0 Then
      23. ' keine Ausgabe bzw. Ausgabewert = 0
      24. Erstmessung = 1
      25. Else
      26. Daten_array(1) = Low(temp)
      27. Daten_array(2) = High(temp)
      28. End If
      29. ' CRC-Pruefsumme
      30. Daten_array(9) = Crc8(daten_array(1) , 8)
      31. End If
      32. 'Goto Readb
      33. Goto Waitreset
      Alles anzeigen

      Beim Auslesen des Scratchpads (s.o.) erhält man nun folgende Werte:
      Wert 1,2 -> Temperatur = (Wert1 + Wert2*256)/10
      Wert 3,4 -> 0
      Wert 5,6 -> 0
      Wert 7 -> leer (evtl. Messung Versorgungsspannung)
      Wert 8 -> Fehlerausgabe
      Wert 9 -> CRC8

      Im Code sind zwei Möglichkeiten als ID vorgesehen:
      Einmal als DS18B20 mit Familiy-Code "&H28",
      zum andern als neuer Bausteintyp mit dem Family-Code "&HFE" (bisher ungenutzt).

      Anschlussbelegung des ATtiny:
      Pin 1 und 8: VCC
      Pin 2: SO (MAX6675)
      Pin 3: SCK (MAX6675)
      Pin 4: GND
      Pin 5: Kontroll-LED (gegen GND)
      Pin 6: 1-Wire-Port
      Pin 7: CS (MAX6675)

      Das wars eigentlich schon.

      1-Wire-Slave_ATtiny45_MAX6675.bas

      02.04.2017 Achtung Änderung des Codes!

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von RoBue ()

    • Dann machen wir mal weiter:
      10. 1-Wire-Slave mit HC-SR04 (Distanzmessung, Füllstandsanzeige)

      Schon seit einiger Zeit wollte ich mal messen können,
      wie viel Öl noch im Tank ist
      oder ob die Regentonne noch voll ist etc.
      und wenn man schon mit 1-Wire arbeitet,
      wäre doch auch so etwas als 1-Wire-Slave gar nicht übel.

      Also frisch ans Werk ...

      Mein Blick fiel auf den Ultraschallsensor HC-SR04.
      Er kann bis zu 3m Distanz berechnen.
      HC-SR04_Breakout.jpg

      Dazu sind folgende Infos interessant:
      -> micropik.com/PDF/HCSR04.pdf
      -> raw.githubusercontent.com/sens…SR04_ultraschallmodul.pdf

      Ich habe daraus mal einen ganz einfachen (primitiven?) Slave gebastelt,
      der in dieser Form sogar noch in einen ATtiny25 passt.

      Anschlussbelegung des ATtiny:
      Pin 1 und 8: VCC ---------- VCC HC-SR04
      Pin 2: -------------------- Trig HC-SR04
      Pin 3: -------------------- Echo HC-SR04
      Pin 4: GND ---------------- GND HC-SR04
      Pin 5: Kontroll-LED (gegen GND)
      Pin 6: 1-Wire-Port
      Pin 7: unbelegt

      Den Baukastencode muss man nur an einer Stelle ändern:

      BASCOM-Quellcode

      1. Calculatedata:
      2. If Match_slave = 1 Then
      3. ' Zaehler fuer Abfrage zuruecksetzen -> Fehlererkennung
      4. Daten_array(8) = 0
      5. ' Sende Signal
      6. Portb.3 = 1
      7. Waitus 10
      8. Portb.3 = 0
      9. ' Warte auf Empfang
      10. Ausgabeinteger = 0
      11. Do
      12. Loop Until Pinb.4 = 1
      13. ' Entfernung messen
      14. While Pinb.4 = 1
      15. ' ungef. 585 us fuer 10 cm
      16. ' Waitus 585
      17. ' ungef. 292 us fuer 5 cm
      18. Waitus 292
      19. Incr Ausgabeinteger
      20. ' Mehr als 3m -> kein Echo
      21. If Ausgabeinteger > 100 Then Exit While
      22. Wend
      23. ' Ausgabe in cm
      24. Ausgabeinteger = Ausgabeinteger * 5
      25. ' Datenarray beschreiben
      26. Daten_array(5) = Low(ausgabeinteger)
      27. Daten_array(6) = High(ausgabeinteger)
      28. ' CRC bestimmen
      29. Daten_array(9) = Crc8(daten_array(1) , 8)
      30. End If
      31. 'Goto Readb
      32. Goto Waitreset
      Alles anzeigen
      Das Scatchpad sieht so aus:
      Byte 1,2 -> unbenutzt oder Temperatur in C x 10 (für später)
      Byte 2,3 -> unbenutzt
      Byte 5,6 -> Distanz in cm
      Byte 7 -> leer (evtl. Versorgungsspannung)
      Byte 8 -> Fehlerausgabe
      'Byte 9 -> CRC

      Meine Messwerte sind ziemlich realistisch und in 5cm-Schritten.
      Aber:
      Wind stört (gibts im Öltank vermutlich weniger ;) , aber evtl. bei der Regentonne).
      Auch die Temperatur beeinflusst das Ganze.
      Deswegen habe ich auch noch die zukünftige Möglichkeit einen zusätzlichen Temperatursensors vorgesehen.

      Leider ist das Breakoutboard so groß,
      dass es sogar fast nicht in den Einfüllstutzen des Öltanks passt.
      Man müsste sich einen neuen Verschluss kaufen und da den Sensor einbauen.
      Ob das zulässig ist, weiß ich leider nicht.

      Ok. Soweit mal.

      Im Anschluss noch der ganze Code.

      Liebe Grüße,
      RoBue

      1-Wire-Slave_HC-SR04.bas

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von RoBue ()