Author Topic: 1-wire am Cubieboard am Beispiel eines DS18B20+ Temperatursensor  (Read 5487 times)

Offline Moustage

  • Newbie
  • *
  • Posts: 2
  • Karma: +0/-0
    • View Profile
Diese Anleitung ist getestet mit Cubieboard 1 und Cubietruck.

Um 1-wire am Cubie nutzen zu können brauchen wir einen Kernel in dem die Module für 1-wire eingepflegt sind.

Man kann recht einfach testen ob der installierte Kernel die benötigten Module dabei hat.
Wir öffnen ein Terminal und geben diese Befehle ein
# sudo modprobe gpio_sunxi
# sudo modprobe w1_sunxi
# sudo modprobe w1_gpio
# sudo modprobe w1_therm

Sollten diese Befehle ohne Fehlermeldung durchlaufen ist alles schick.
Ansonsten bleibt nur den Kernel selber bauen oder einen verwenden der diese Module dabei hat,
für das Cubieboard 1 musste ich den Kernel neu kompilieren, beim Kernel von Danand sind sie dabei.

Zur Sicherheit nochmals testen mit
#lsmod
sollte uns jetzt die geladenen Module anzeigen, neben anderen...

Module                  Size  Used by
...
w1_therm                2857  0
w1_gpio                 1308  0
wire                   26176  2 w1_gpio,w1_therm
w1_sunxi                 908  0
gpio_sunxi              9003  1
...


Grundsätzlich sollte jeder freie Pin funtionieren, aber Achtung einige sind schon belegt.

Beim Cubieboard 1+2 bietet sich der Port PB10 an, da direkt daneben GND und 3,3V zu finden sind
(Pins 40 = PB10, 42 = GND und 44 = 3,3V Expansionsport U14, Pin 1 ist beim Sata).
Die Belegung ist zu finden unter http://linux-sunxi.org/Cubieboard/ExpansionPorts

Beim Cubietruck verwende ich den Port PG3 (Pin 2 = 3,3V, 4 = PG3 und 16 = GND Expansionsport CN9
auf der USB - VGA Seite, Pin 1 ist beim VGA).
Die Belegung ist zu finden unter http://linux-sunxi.org/Cubietruck#Expansion_Ports

In der script.bin bzw script.fex Datei (wegen Umwandlung siehe http://linux-sunxi.org/Sunxi-tools)
muss der benützte gpio_pin eingetragen werden (bei meinem Cubieboard 1 war das alles noch gar nicht definiert).

[gpio_para]
gpio_used = 1               # Anzeigen das GPIO benutzt wird
gpio_num = 1       # Anzahl der benutzten Portpins Cubie 1+2 = 1 // Cubietruck = 3
# für Cubie 1+2             #gpio_pin_1 = port:PB10<0><default><default><0>
# für Cubietruck            #gpio_pin_3 = port:PG3<0><default><default><0>

[w1_para]
gpio = 1   # den zu benutzenden gpio_pin_X eintragen // die Nummer (1 oder 3 laut obigem Beispiel)


Um die Temperatur messen zu können benötigen wir einen 4k7 Ohm Widerstand und natürlich einen DS18B20+,
als Buchsenleiste nehme ich BL 2X10G 2,00, gibts alles z.B. bei Reichelt.

Für mehrere DS18B20+ benötigen wir KEINEN weiteren Widerstand - nur diesen einen (Pullup).
Den Widerstand löten wir an der Buchsenleiste zwischen 3,3V und dem PB10 (Pin 40) oder PG3 (Pin 4), je nach unserem Board,
beim DS18B20+ ist der mittlere Pin die Datenleitung und die beiden Äusseren + und GND,
am besten einen Blick ins Datenblatt werfen http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf

Nochmals kontrollieren ob auch kein Kurzschluss und die Lötungen alle an der richtigen Stelle,
dann können wir endlich die Buchsenleiste aufstecken und das Cubieboard einschalten.
Ein Tipp: sollte der DS18B20+ sehr heiss werden, habt ihr +3,3V und GND vertauscht...
Der Sensor kann auch parasitär arbeiten (nur 2 Kabel benötigt), das hab ich aber nicht zum laufen bekommen.

Nochmals die vier Befehle von oben eingeben und nachsehen welche 1-wire Adressen wir haben,
jeder DS18B20+ hat eine eizigartige Nummer!
# ls /sys/bus/w1/devices
je nachdem wieviele DS18B20+ wir angeschlossen haben (glaube bis 10 Stück gehen ohne Probleme),
sollte jetzt ein oder mehrere Ordner vorhanden sein der/die 28-XXXXXXXXXXXX lautet.
Bei mir z.B. 28-0000050b3964 bei euch steht hinter der 28- garantiert eine andere Zahl!

Jetzt wirds Spannend, mit einem
#cat /sys/bus/w1/devices/28-EUER_DS18B20+/w1_slave
bekommen wir zwei Zeilen angezeigt z.B.

7b 01 4b 46 7f ff 05 10 1d : crc=1d YES
7b 01 4b 46 7f ff 05 10 1d t=23687
das YES in der ersten Zeile zeigt euch, dass der Wert gültig ist, bei einem NO wiederholen wir den Befehl.
in der zweten Zeile steht neben dem t= die aktuelle Temperatur in Grad Celsius,
den Wert noch schnell durch 1000 teilen und wir haben die aktuelle Temperatur (am Gehäuse des DS18B20+)!

Um das alles immer zur Verfügung zu haben, editieren wir die Datei /etc/modules mit root-rechten
und tragen die vier Befehle ein (ohne sudo und ohne modprobe, immer einen pro Zeile).
gpio_sunxi
w1_sunxi
w1_gpio
w1_therm

Noch einen reboot und fertig!

Viel Spaß beim Temperatur messen...
und das alles erweitern z.B. auf dem Webserver anzeigen, Temperuturanzeige auf dem Monitor oder Ausbau zur Wetterstation usw.  ;)

Offline ikaruzz

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
    • View Profile
Re: 1-wire am Cubieboard am Beispiel eines DS18B20+ Temperatursensor
« Reply #1 on: September 20, 2014, 09:37:08 am »
Danke für die Anleitung

Hab es mal auf meinem Cubietruck ausprobiert und es funktionierte fast!
Zunächst erschien das Device 28-XXXXXXXXXXXX nicht.

Während ich dann weiter testete und gleichzeitig auf meinem Cubietruck einen neuen Kernel baute, funktionierte es dann.
Konnte dann feststellen, das das Device da und lesbar war, wenn das System Last hat - wenn das System keine Last hatte, verschwand das Device wieder.
(Zur Referenz sei noch gesagt, dass ich die Kernelsourcen von Danand verwende und auf dem Cubietruck gentoo-linux verwende)
Da ich cpufrequtils verwende schaltet die CPU bei "idle" runter auf 60MHz, bei Vollast auf 1.008 GHz.
Habe dann mal schrittweise die minimale Taktfrequenz angehoben.

Mit
Code: [Select]
echo  528000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq(also 528Mhz als minimum für "idle")
war das Device dann immer sichtbar und die Temperatur lesbar.

Da ich auf meinem zweiten Cubietruck mit dem Mainline-Kernel (3.17-rc2 mit neuerem uboot und "Device Tree" statt "fex") teste, hab ich mal Google genutzt, um herauszufinden wie man die Anleitung nach "Device Tree" übersetzten könnte.
Unter http://linux-sunxi.org/1-Wire wurde ich dann fündig.

Da ich wie in der Anleitung von "Moustage" vorgeschlagen "PG3" verwende, passt die Anleitung für die Variante mit dem "Device Tree" dort nicht ganz.

Habe dann in der pinctrl@01c20800 section von sun7i-a20-cubietruck.dts
Code: [Select]
  w1_pins_cubietruck: w1_pins@0 {
  allwinner,pins = "PG3";
  allwinner,function = "gpio_out";
  allwinner,drive = <1>;
  allwinner,pull = <0>;
  };
eingefügt und vor der letzten geschweiften Klammer am Ende noch
 
Code: [Select]
w1@0 {
  compatible = "w1-gpio";
  pinctrl-names = "default";
  pinctrl-0 = <&w1_pins_cubietruck>;
  gpios = <&pio 6 3 0>;
  status = "okay";
  };
eingefügt.

Mit "make dtbs" den "Device Tree" neu gebaut, sun7i-a20-cubietruck.dtb nach /boot kopiert und rebootet.
Hier funktionierte dann alles sofort (verwende dort noch nicht cpufrequtils).


4x Raspberry Pi Modell B, 1x  Raspberry Pi Modell B+, 1x Cubieboard1, 2x Cubieboard2, 2x Cubietruck, 2x NVIDIA Jetson TK1, 1x Wandboard Quad C1

Offline Moustage

  • Newbie
  • *
  • Posts: 2
  • Karma: +0/-0
    • View Profile
Re: 1-wire am Cubieboard am Beispiel eines DS18B20+ Temperatursensor
« Reply #2 on: October 01, 2014, 08:18:42 am »
Anbei mal mein Versuch die Sensoren mit Python auszulesen,
da ist sicherlich noch hoher Optimierungsbedarf - ist mein erster Versuch mal was in Python zu machen.
Vielleicht gibt es ja hier Profis, die das noch verbessern können  :D

Das Programm macht folgendes:
es durchsucht das Verzeichnis wo die Dateien der Sensoren liegen, anschließend liest es die Sensoren und gibt die Werte aus.
Code: [Select]
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys

DEVICE_DIR = "/sys/bus/w1/devices/"
DEVICE_SLAVE = "/w1_slave"

sensoren = []
temperatur = []

###########################################################
# Anzahl und Nummern der angeschlossenen Sensoren ermitteln
###########################################################
def get_sensors(sensoren):
  sensoren_anzahl = 0
  for x in os.listdir(DEVICE_DIR):
    if "28-" in x: # die DS18B20 gehören zur Familie 28-X
      sensoren.append(x)
      sensoren_anzahl += 1

    if sensoren_anzahl == 0:
      print "Keine Sensoren gefunden"
      sys.exit(0) # keine Sensoren gefunden, Schluss

  print sensoren_anzahl, "Sensoren gefunden"
  return sensoren

###################################
# Temperatur einlesen und auswerten
###################################
def get_temperatur(sensor):
  sensor_adress = DEVICE_DIR + sensor + DEVICE_SLAVE
  sensor_open = open(sensor_adress, 'r')
  sensor_wert = sensor_open.read()
  sensor_open.close()
  if "NO" in sensor_wert: # manchmal liefern die Sensoren keine gültigen Werte
    sensor_wert = 9999
    return sensor_wert
  if "YES" in sensor_wert: # Temperatur ist gültig
    temp = float(sensor_wert.split("\n")[1].split(" ")[9].split("t=")[1])  # Temperatur auslesen
    temp /= 1000.0 # und auf Grad Celsius umrechnen
  return temp


####################################
# Hauptprogramm einlesen der DS18B20
####################################

sensoren = get_sensors(sensoren) # Sensorenliste generieren

for x in sensoren: # alle Sensoren einlesen
  lines = get_temperatur(x)
  while lines == 9999: # Sensor lieferte Fehlerwert
    lines = get_temperatur(x) # nochmals lesen
  print "Sensor", x, "=", lines # Ausgeb Temperatur und Sensor