Kategorien
Allgemeine Beiträge Software & Code

Beispiel-Code: Interoperatibilität DS18B20 & 24C32

Stefans Schwerpunkte liegen im Umfeld von Betriebssystemen, serverbasierten Diensten und im weitesten Sinne in allgemeiner technischer Infrastruktur. Tagsüber mit strategischen IT-Themen beschäftigt, tackert er Nachts doch mal gerne ins schwarze Loch.
swarkn
Letzte Artikel von swarkn (Alle anzeigen)

Dieses Beispiel gehört zur Baugruppe: Tiny RTC I2C Module und dient der Veranschaulichung der Interoperatibilität zwischen dem DS18B20 Temperatursensor und dem 24C32 EEPROM. Die Daten des OneWire Temperatursensors werden gelesen und im EEPROM via I2C gespeichert.

Ihr könnt das Beispiel noch erweitern, in dem Ihr das EEPROM mit Sensordaten füllt und danach einen „roll-over“ macht. Interessant wäre dann, sich noch die letzte Speicherposition im EEPROM zu merken, um bei Stromausfall wieder an der richtigen Stelle aufzusetzen. Oder man könnte sich natürlich noch die Uhrzeit mit speichern. Oder, oder, oder … 🙂

Screenshot des seriellen Monitors

DS18x20 and 24C32
//
//    This is a demo, how to use the DS18x20 and the 24C32 EEPROM from an "Tiny RTC I2C module" package all together.
//    Stefan (swarkn) from http://www.do-it-neat.com
//
//    This demo need the following libraries:
//      https://github.com/PaulStoffregen/OneWire
//      https://github.com/Soshimo/I2C-Serial-EEPROM-Arduino-Library
//
//    Please note: I put temperature and EEPROM things appart to better understand and read the code.
//    

// includes
#include <Wire.h>
#include <i2cEEPROM.h>
#include <OneWire.h>

OneWire ds(10);                           // D18x20 Temperature chip i/o on pin 10 at your uno/nano/etc.

// global variables
byte i;                                   // counter
byte data[12];                            // hold read data
byte addr[8];                             // OneWire address of the first DS18x20 found

void setup(void) {
  // start serial port
  Serial.begin(9600);

  //// 
  //// Start DS18x20 setup
  ////
  
  // search address
  ds.reset_search();
  if ( !ds.search(addr)) {
      Serial.print("No more addresses.\n");
      ds.reset_search();
      return;
  }

  // check device address correctness
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }
  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }

  // identify device by ID
  if ( addr[0] == 0x10) {
      Serial.print("Device is a DS18S20 family device.\n");
  }
  else if ( addr[0] == 0x28) {
      Serial.print("Device is a DS18B20 family device.\n");
  }
  else {
      Serial.print("Device family is not recognized: 0x");
      Serial.println(addr[0],HEX);
      return;
  }
  Serial.println();

  ////
  //// Start 24C32 setup
  ////
  i2cEEPROM.begin(0x50);                // start communicating to I2C device 0x50h

}

void loop(void) {

  ////
  //// Do the DS18x20 operations
  ////

  ds.reset();                           // wire reset pulse
  ds.select(addr);                      // select device found in setup phase
  ds.write(0x44,1);                     // command: convert T, with parasite power on at the end

  ds.depower();                         // set DS to low (only in parasite power mode)
  
  ds.reset();                           // wire reset pulse
  ds.select(addr);                      // select device found in setup phase
  ds.write(0xBE);                       // DS18x20 command: read scratchpad

  Serial.print("Read data from DS18x20: ");
  for ( i = 0; i < 9; i++) {            // 9 bytes of scratchpad: 0-1b=temperature, 2-3b=alarm trigger register/user byte 1+2, 4b=configuration register, 5-7b=reserved, 8b=CRC
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  
  ////
  //// Do the 24C32 operations
  //// 

  Serial.print("Write to EEPROM: ");
  for ( i = 0; i < 9; i++) {            // write the 9 bytes of scratchpad into EEPROM
    i2cEEPROM.writeByte(i,data[i]);     
    Serial.print(i2cEEPROM.readByte(i), HEX);
    Serial.print(" ");
  }
  Serial.println();

  Serial.print("Read from EEPROM: ");
  for ( i = 0; i < 9; i++) {            // read the 9 bytes of scratchpad from EEPROM
    Serial.print(i2cEEPROM.readByte(i), HEX);
    Serial.print(" ");
  }
  Serial.println();
  Serial.println();
  
  ////
  //// wait some time
  //// 
  delay(1000);

}

Viel Spaß damit :),
swarkn

pinterest
Kategorien
Erklärbär & Anleitungen Software & Code

Datei- und Verzeichnisrechte unter Linux sichern

Stefans Schwerpunkte liegen im Umfeld von Betriebssystemen, serverbasierten Diensten und im weitesten Sinne in allgemeiner technischer Infrastruktur. Tagsüber mit strategischen IT-Themen beschäftigt, tackert er Nachts doch mal gerne ins schwarze Loch.
swarkn
Letzte Artikel von swarkn (Alle anzeigen)

Hallo zusammen,

Die Möglichkeit des sicherns von Datei- und Verzeichnisrechten unter Linux war mir bereits mehrfach extrem hilfreich. Hier zeige ich euch, wie das funktionieren kann.

Schon einmal während der Fehlersuche in einem Unterverzeichnis alles auf 777 gesetzt? Danach hat es vielleicht sogar funktioniert – was bedeutet, dass der Grund eures Fehlers sicher etwas mit Zugriffsrechten im Dateisystem zu tun hat – allerdings sind damit die originalen Datei- und Verzeichnisrechte „futsch“.

Klar kann man sich vorher einen tar-ball ziehen. Geht aber auch geschickter. *daumenhoch*

Der Einzeiler: „Datei- und Verzeichnisrechte unter Linux sichern“

Ich möchte euch heute einen Einzeiler vorstellen, der mir persönlich schon einige Male gute Dienste erwiesen hat:

find ./ -exec sh -c 'echo "chown `stat -c %u:%g \"{}\"` \
\"{}\"; chmod `stat -c %a \"{}\"` \"{}\""' \;

Das Ergebnis ist ziemlich spannend. Der Einzeiler „wirft“ chown und chmod Zeilen (eine Zeile für jede Datei oder Verzeichnis im aktuellen Verzeichnis und abwärts) aus, die direkt ausgeführt werden können um die Berechtigungen wieder zurückzusetzen. Wenn man also die Ausgabe des Befehls in eine Datei umleitet, so erhält man ein bash-Skript, welches die Berechtigungen der ausgelesenen Dateien 1:1 wieder herstellt. *daumenhoch*

Mag dem ein oder anderen vielleicht wie alter Käse vorkommen – nach meiner Erfahrung kennen viele diese Möglichkeit aber leider nicht.

Vom Erklärbären: Wie genau funktioniert nun der Einzeiler „Datei- und Verzeichnisrechte unter Linux sichern“

find ./

Der erste Teil des Einzeilers ist der Befehl find. Dieser listet ohne weitere Parameter alle gefundenen Datei- und Verzeichnisnamen in voller Länge auf. Setzt man wie ich in diesem Beispiel einen Punkt vor den Forward-Slash, so erhält man relative Datei- und Verzeichnisnamen zum aktuellen Verzeichnis bei Befehlsausführung. Diese Liste benötigen wir, um jedes Verzeichnis und jede Datei bei unserer Ausgabe zu berücksichtigen.

Der Befehl find hat einen interessanten Parameter: -exec [Befehl] \;. Dieser weisst dem Befehl find an, pro ausgegebener Zeile einen Befehl auszuführen. Wichtig ist, dass der Befehl mit einem Back-Slash und einem Semikolon abschließt. So weiß find, wo der „exec“ Befehl auch tatsächlich endet. In unserem Fall möchten wir gerne, das eine Shell aufgerufen wird, in der ein weiteres Kommando ausgeführt wird. Um eine Shell aufzurufen und direkt ein Kommando auszuführen (und die Shell wieder schliessen zu lassen), kann man folgenden Befehl verwenden:

sh -c 'echo "Diese Ausgabe kommt aus einer eigenen Shell"'

Seltsam. Wenn der Befehl find schon ein Kommando ausführen kann, warum rufen wir eine Shell auf, die selbst ein Kommando ausführt? Berechtigte Frage. Leider ist die Möglichkeit der Befehlsausführung durch find sehr begrenzt. Find mag z.B. nicht, wenn Ausgaben zu sehr manipuliert – also wie in unserem Fall – erweitert werden. Aus diesem Grund überlassen wir das schön einer Subshell.

Der eigentlich pro durch find gefundenes Verzeichnis oder Datei ausgeführte Befehl lautet dann:

echo "chown `stat -c %u:%g \"{}\"` \"{}\""

Jetzt wird es ein wenig komplizierter. Aber ich versuche mich einzeln „durchzuhangeln“. Zur Vereinfachung habe ich das sich wiederholende Schema im kompletten Befehl gekürzt.

Was auf den ersten Blick klar sein dürfte ist, dass der Befehl echo die fertigen Befehlszeilen ausgibt. Auffällig ist die Verwendung eines weiteren Kommandos namens stat, die Verwendung des schrägen Single-Tick: ` und der Zeichenkombination \"{}\".

Als ersten sollte ich mit der Verwendung des besonderen Single-Tick beginnen. Dieses ` weißt die aktuelle Shell (also die Shell die wir durch find und dessen Parameter -exec haben aufrufen lassen) an, ein Kommando zu substituieren. Soll heißen: Die Ausgabe des Befehles zwischen diesen Single-Ticks wird an die Stelle des auszuführenden Befehls gesetzt.

Vielleicht macht es Sinn, das Beispiel an dieser Stelle weiter zu vereinfachen:

echo "`stat -c %u:%g /etc/profile`"

Die Ausgabe sollte: 0:0 entsprechen. Der Befehl stat gibt mit den Parametern -c %u:%g und anschliessender Verzeichnis- oder Dateiangabe die owner- und group-ID zurück. Da das Kommando substituiert ausgeführt wird, ersetzt es sich selbst in den Parametern des Befehles echo durch seine eigene Ausgabe: echo "0:0"

Jetzt bleibt tatsächlich nur noch das Geheimnis der Zeichenkombination \"{}\", welches irgendetwas mit Verzeichnis- und Dateinamen zu tun haben muss.

Richtig. Aber eigentlich handelt es sich genau genommen nur um die beiden Curly-Brackets {}. Diese weissen das Kommando find vor der Ausführung des -exec Parameters an, an dieser Stelle (wo und wie oft auch immer angegeben) den aktuell gefundenen Verzeichnis oder Dateinamen einzufügen. So kommt der Befehl stat dann auch an seinen benötigten Parameter um die owner- und group-ID auszulesen.

Die doppelten Anführungszeichen sorgen nur dafür, dass bei Leerzeichen in Datei- oder Verzeichnisnamen keine Fehler bei späterer Skriptausführung auftreten.

So, dass war’s wieder. Ich hoffe der Einzeiler „Datei- und Verzeichnisrechte unter Linux sichern“ macht Sinn und ist euch vielleicht ebenso nützlich wie er mir schon oft war. 🙂

Viel Spaß,
swarkn

pinterest