Aus Raspberry Pi Geek 06/2015

EEPROM-Speicher mit dem Raspberry Pi nutzen (Seite 3)

Abbildung 4: Die Kommandos des SPI EEPROM 25A512 erlauben es, Daten auf den Speicherbaustein zu laden und von diesem wieder auszulesen.

Abbildung 4: Die Kommandos des SPI EEPROM 25A512 erlauben es, Daten auf den Speicherbaustein zu laden und von diesem wieder auszulesen.

Zeile 22 stellt einen Takt von knapp 2 MHz ein, zwanzigmal schneller als der I2C-Bus in den Grundeinstellungen. Der Schreibvorgang ab Zeile 24 ist spezifisch für den 25A512 und sieht bei anderen Chips eventuell etwas anders aus. Dem Muster folgen im Prinzip aber viele Chips: das Schreiben ankündigen (WREN) und dann einen ganzen Block hintereinander in den Chip schieben.

Anschließend benötigt der Baustein etwas Zeit zum Arbeiten (Zeile 37); 5 Millisekunden hätten hier genügt. Das Lesen mehrerer Bytes an einem Stück klappt beim 25A512 ebenfalls in einem Rutsch. Der 24C32N konnte das oben per I2C-Bus nur byteweise.

Umweg über Arduino

Etwas einfacher gelingt die Programmierung über den Umweg, einen Arduino zur Kommunikation mit dem EEPROM zu nutzen. Die entsprechenden Bibliotheken und Programme erweisen sich als wahre Fundgrube, um sich auf der Bit-Ebene mit Sensoren und EEPROMs zu beschäftigen.

Um das Programmieren über den Arduino zu demonstrieren, kommt an dieser Stelle ein praktisches Beispiel zum Einsatz, bei dem ein Arduino als kleines Radio seine Senderliste vom RasPi empfängt und diese in sein eingebautes EEPROM speichert. Abbildung 5 zeigt den experimentellen Prototypen, in Listing 7 sehen Sie einen Ausschnitt aus der vom RasPi übertragenen Senderliste.

Abbildung 5: Ein Arduino-Radio mit einem EEPROM als Speicher für die Senderauswahl.

Abbildung 5: Ein Arduino-Radio mit einem EEPROM als Speicher für die Senderauswahl.

Listing 7

 

Freq;RDS;Programm;Distanz;dBuV
91.4;BRF 91.4;Berliner Rundfunk 91.4 (Berlin);1km;112
95.8;radio1;RBB Radio Eins;1km;112
97.7;DLF;Deutschlandfunk (DLF);1km;112
99.7;Antenne;Antenne Brandenburg (Potsdam);1km;112
94.3;94,3 rs2;r.s.2;1km;106
89.6;DKULTUR;Deutschlandradio Kultur;1km;105
90.2;TEDDY;Radio Teddy;1km;104
100.6;FluxFM;FluxFM 100,6;1km;104
102.6;Fritz;RBB Fritz;1km;104
104.6;104.6RTL;104.6 RTL;1km;102
103.4;ENERGY;Energy Berlin;1km;101
105.5;SPREE;105'5 Spreeradio;1km;99
101.3;KLASSIK;Klassik Radio (Berlin);1km;98
93.6;JAM FM;Jam FM;1km;95
87.9;STAR FM;STAR FM 87.9;1km;92

Der RasPi schickt die ersten 15 Einträge der Liste mit einem Python-Skript (Listing 8) an den per USB-Port angeschlossenen Arduino. In diesem Fall sucht der Rechner nach einem Arduino Leonardo am USB-Port. Anschließend öffnet das Skript eine serielle Konsole und sendet das Code-Wort knock. Damit weiß das Programm in Listing 9 auf dem Arduino etwas anzufangen: Es antwortet mit einem OK und die Übertragung beginnt.

Listing 8

 

#!/usr/bin/env python
import serial
import re
import serial.tools.list_ports
import time
station_file = 'stations.txt'
counter = 0
top15_sender = []
for line in open(station_file):
  if re.match(r'^\d+',line):
    counter += 1
    top15_sender.append(line.rstrip().split(';'))
  if counter > 15:
    break
for sender in top15_sender:
  print ';'.join(sender[0:2])
ser_port = ''
ports = list(serial.tools.list_ports.comports())
for p in ports:
  if re.match(r'.*2341:8036',p[2]):
    print "Arduino Lenonardo gefunden."
    ser_port = p[0]
if ser_port == '':
  print "Kein passender Arduino gefunden."
  print p
  exit()
ser = serial.Serial(ser_port, 38400, timeout=None)
ser.write('knock')
line = ser.readline().rstrip()
if line == 'OK':
  print line
  for sender in top15_sender:
    to_send = ';'.join(sender[0:2])
    ser.write(to_send)
    print to_send
    line = ser.readline().rstrip()
    if line != 'OK':
      print "Da ging was schief!"
      exit()
    time.sleep(3)

Der Ausschnitt aus dem Arduino-Programm in Listing 9 fasst die wesentlichen Funktionen zusammen. Der Aufwand für die Kommunikation mit dem EEPROM reduziert sich auf die vier Funktionen EEPROM.update(), EEPROM.read(), EEPROM.put() und EEPROM.write(). Der Rest des Programms kümmert sich um die Kommunikation mit der seriellen Schnittstelle und bringt die Daten in die passende Form.

Listing 9

 

#include <Wire.h>
#include <EEPROM.h>
boolean knock = false;
struct radio_station {
  char freq[6];
  char rds[17];
};
void init_eeprom(boolean reset=false) {
  EEPROM.update(0,'I');
  if(reset) EEPROM.update(1,0);
}
void show_eeprom() {
  radio_station station;
  int size_of_station = sizeof(station);
  int count = EEPROM.read(1);
  Serial.print(count);Serial.print(":");
  for(int i=0;i<EEPROM.read(1);i++) {
    EEPROM.get(2+i*size_of_station, station);
    Serial.print(station.freq);Serial.print(';');Serial.println(station.rds);
  }
}
void get_station(byte nr, struct radio_station &station) {
  byte size_of_station = sizeof(station);
  byte count = EEPROM.read(1);
  if (nr>count) nr = count;
  if (nr<1) nr = 1;
  EEPROM.get(2+(nr-1)*size_of_station, station);
}
void setup() {
  init_eeprom();
  Serial.begin(38400);
  Serial.println("RadioXZ");
}
void loop() {
  radio_station station;
  if(Serial.available()>0) {
    String line = String(Serial.readString());
    switch(line.charAt(0)) {
      case 'k': Serial.println("OK");
        knock = true;
        break;
      case 'r': Serial.println("RESET");
        init_eeprom(true);
        knock = false;
        break;
      case 's': show_eeprom();
        break;
      default:
        if(knock==true) {
          int idx = line.indexOf(';');
          if(idx != -1) {
            String f = String(line.substring(0,idx));
            f.toCharArray(station.freq,6);
            station.freq[f.length()] = 0;
            String r = String(line.substring(idx+1));
            r.toCharArray(station.rds, 16);
            station.rds[r.length()] = 0;
            byte counter = EEPROM.read(1);
            EEPROM.put(2+(counter*sizeof(station)), station);
            delay(500);
            counter = (counter % 16) + 1;
            EEPROM.write(1,counter);
            Serial.println("OK");
          }
        }
        break;
    }
  }
}

Fazit

Bei EEPROMs handelt es sich im Grunde genommen um ein elektronisches Fossil, es gibt sie schon seit fast 40 Jahren. Trotz der geradezu winzig anmutenden Kapazität genügen sie jedoch für viele Anwendungen in der Welt der Mikrocontroller. Ihr Einsatz erfordert etwas Übung beim Programmieren und das Studium von Datenblättern; mit den passenden Bibliotheken fällt der Einstieg jedoch leicht.

Solange es nicht auf Geschwindigkeit ankommt, geben Sie am besten EEPROMs für den I2C-Bus den Vorzug: Er ist unter Linux auf dem RasPi gut unterstützt, wie das Beispiel mit den I2C-Tools zeigt. Alle vorgestellten Beispiele erweitern Sie bei Bedarf leicht zu eigenen Anwendungen. So böte es sich an, den EEPROM in der Echtzeituhr zum Speichern von Weckzeiten oder Terminen zu verwenden. 

Der Autor

Marcus Nasarek ist Linux seit Langem treu und schwer begeistert von Skripting, von Ruby und von Projekten mit dem Raspberry Pi.

Infos

  1. Einführung in den I2C-Bus: Martin Mohr, “I-Quadrat-C”, RPG 01/2015, S. 68, http://www.raspi-geek.de/33535
  2. Echtzeituhr via I2C programmieren: https://raspilab.wordpress.com/2014/10/30/eine-echtzeituhr-mit-dem-i2c-bus-anprogrammieren/
  3. Datenblatt 24C32N: http://www.atmel.com/images/doc0336.pdf
  4. Bcm2835-Library: http://www.airspayce.com/mikem/bcm2835/index.html
  5. Datenblatt 25A512: http://ww1.microchip.com/downloads/en/DeviceDoc/22237C.pdf
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 8 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben