Go Down

Topic: Probleme mit SPI und mehreren I2C Devices ? (Read 164 times) previous topic - next topic

ArdunioArti

Dec 25, 2019, 11:49 am Last Edit: Dec 25, 2019, 11:56 am by ArdunioArti
Hallo, 

ich habe bei meinem aktuellen Projekt ein Problem bei dem ich nicht mehr weiterkomme.
Der Hardwareaufbau sieht folgendermaßen aus.


Leider bekomme ich dieses Setup nicht zum laufen sobald ich die Folientastatur anschließe.

Der Sketch sieht aktuell fogendermaßen aus.

[Kommt im nächsten Beitrag da sonst die maximale Länge des Beitrags überschritten ist]

Sobald ich über die Zeile
Keypad_I2C i2cKeypad( makeKeymap(tastenLayout), zeilenPins, spaltenPins, anzZeilen, anzSpalten, I2CADDR);
Das Keypad einbinde funktioniert das Laden von der SD Karte nicht mehr.

Zusätzlich wird noch folgender Hinweis angezeigt:
Quote
Der Sketch verwendet 22712 Bytes (70%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 1653 Bytes (80%) des dynamischen Speichers, 395 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.
Die I2C devices haben laut meinen Messungen folgenden Pull-up Widerstand. Datenloggershield 2,2kΩ PCF8574T 1kΩ und I2C für Display 4,65 kΩ. Das sollte einen Gesamtwiderstand von 0,59 kΩ ergeben was ja eigentlich zu wenig für I2C bei 5V ist. Allerdings funktioniert das Display bei diesem Hardwaresetup und auch die Folientastaur funktioniert bei diesem Hardwaresetup wenn ich nur einen Sketch zum Prüfen der tastatur aufspiele.

Kann es an einem Konflikt der verwendeten PINs für das Datenloggermudul (SPI) und den I2C devices liegen ?

Ist das Problem wirklich der geringe Arbeitsspeicher oder wo sollte ich den Fehler suchen ?
Wenn ja kann ich da überhaupt irgendwas machen um das Problem zu beheben ?

Vielen Dank schonmal
ArduinoArti

ArdunioArti

Code: [Select]
#include <Wire.h>            
#include <LCD.h>              
#include <LiquidCrystal_I2C.h>
#include <SPI.h>              
#include <SD.h>                
#include "RTClib.h"          
#include "DHT.h"              
#include <Keypad_I2C.h>        
#include <Keypad.h>          

#define I2C_ADDR    0x27       // I2C Addresse des I2C Controllers definieren für 2x16 Segementanzeige
#define BACKLIGHT_PIN     3    // Anschluss für die Hintergrundbeleuchtung definieren für 2x16 Segementanzeige

#define aussensensorPIN 8      // Digital pin connected to the DHT Aussensensor
#define innensensorPIN 9       // Digital pin connected to the DHT Innensensor
#define DHTTYPE DHT22          // DHT 22  (AM2302), AM2321
#define I2CADDR 0x20      // I2C Adresse vom PCF8574 (Keypad)

const byte anzZeilen = 4;                        // Anzahl Zeilen Keypad
const byte anzSpalten = 4;                       // Anzahl Spalten Keypad
char tastenLayout[anzZeilen][anzSpalten] = {     // Symbole Keypad
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
                                                 //Hier definieren wie das Keypad mit den IO Pins vom PCF8574 verdrahtet ist.
byte zeilenPins[anzZeilen] = {0, 1, 2, 3};       //Zeilen Pins
byte spaltenPins[anzSpalten] = {4, 5, 6, 7};     //Spalten Pins


const String SetupDatei = "/setup.csv";        // Dateiname für die Betriebseinstellung
const int chipSelect = 10;                     // Für Datenlogger Modul am Arduino Uno so lassen

float t_innen;         // Temperatur Innensensor
float h_innen;         // Luftfeuchtigkeit Innensensor
float absolut_innen;   // Absolute Luftfeuchtigkeit innen
float t_aussen;        // Temperatur Aussensensor
float h_aussen ;       // Luftfeuchtigkeit Aussensensor
float absolut_aussen;  // Absolute Luftfeuchtigkeit aussen


//Keypad_I2C i2cKeypad( makeKeymap(tastenLayout), zeilenPins, spaltenPins, anzZeilen, anzSpalten, I2CADDR); //Initialisierung von Keypad
LiquidCrystal_I2C lcd(I2C_ADDR,2,1,0,4,5,6,7,BACKLIGHT_PIN,POSITIVE); // für 2x16 Segementanzeige
RTC_DS1307 rtc; // für RTC
DHT aussensensor(aussensensorPIN, DHTTYPE); // Aussensensor definieren
DHT innensensor(innensensorPIN, DHTTYPE); // Innensensor definieren

void setup()
{  
//  i2cKeypad.begin( );          
  lcd.begin(16,2);              

   while (!Serial); // for Leonardo/Micro/Zero

  Serial.begin(9600);

    // Start Statusprüfung RTC
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);                  //Läuft nicht weiter
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  }

  lcd.setCursor(0,0);                                                        // Wenn die RTC
  lcd.print("RTC running");                                                  // läuft wird
  DateTime now = rtc.now();                                                  // das Datum
  String Uhrzeit = "";                                                        // für 3 Sekunden
  Uhrzeit = (String(now.day())) + "." + now.month() + "." + now.year() + " " + now.hour() + ":" + now.minute() ;       // auf dem LCD
  lcd.setCursor(0,1);                                                        // angezeigt
  lcd.print(Uhrzeit);                                                         // ...
  delay(2000);                                                               // ...

  
 // Ende Statusprüfung RTC

// Start Statusprüfung SD Karte

if (!SD.begin(chipSelect)) // Wenn die Initialisierung der SD Karte NICHT! erfolgreich war
 {Serial.println("SD Karte Fehler");
  lcd.clear();
  lcd.setCursor(0,0);                                                        
  lcd.print("SD Karte Fehler");
  while (1);                          //Läuft nicht weiter
 }
else {

  Serial.println("SD Karte initialisiert");
  lcd.clear();
  lcd.setCursor(0,0);                                                        
  lcd.print("Speicherkarte");
  lcd.setCursor(0,1);                                                        
  lcd.print("initialisiert");
  delay (3000);

 }
// Ende Statusprüfung SD Karte

  
 
if (!(SD.exists(SetupDatei))) //Wenn die SetupDatei NICHT existiert
   {
    Serial.println("Setupdatei nicht vorhanden");
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Setupdatei");
    lcd.setCursor(0,1);                                                        
    lcd.print("nicht vorhanden");  
    delay(3000);
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Standardsetup");
    lcd.setCursor(0,1);                                                        
    lcd.print("wird geschrieben");    

    File SetupFile = SD.open(SetupDatei, FILE_WRITE); // Datei zum Schreiben öffnen.

      if (SetupFile) // Wenn Datei zum schtreiben bereit ist, schreibe hinein
      {
      SetupFile.println("1;");
      SetupFile.println("5;30;");
      }
    SetupFile.close(); // Datei schließen

    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Standardsetup");
    lcd.setCursor(0,1);                                                        
    lcd.print("wurde geschrieben");
    
    }
 else
    {
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Setupdatei");
    lcd.setCursor(0,1);                                                        
    lcd.print("wird geladen");  
    
       // open the file for reading:
   File SetupFile = SD.open(SetupDatei);
  if (SetupFile) { // if the file opened

    
    // read from the file until there's nothing else in it:
    while (SetupFile.available()) {
     Serial.write(SetupFile.read());
    }
    // close the file:
    SetupFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("Laden der Setupdatei fehlgeschlagen");
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Laden Setupdatei");
    lcd.setCursor(0,1);                                                        
    lcd.print("fehlgeschlagen");
    delay(2000);
  }
   //  
    
     }  


 
 aussensensor.begin(); // Aussensensor starten
 innensensor.begin(); // Innensensor starten

}

void loop()
{
  lcd.setBacklight(HIGH); // für 2x16 Segementanzeige
  DateTime now = rtc.now();
  

//Beginn Sensor

  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h_aussen = aussensensor.readHumidity();     // Read humidity in %
  t_aussen = aussensensor.readTemperature();  // Read temperature as Celsius (the default)
  h_innen = innensensor.readHumidity();       // Read humidity in %
  t_innen = innensensor.readTemperature();    // Read temperature as Celsius (the default)

  // Check if any reads failed and exit early (to try again).
  if (isnan(h_innen) || isnan(t_innen)) {
    Serial.println(F("Keine Daten: Innensensor"));
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Keine Daten");
    lcd.setCursor(0,1);                                                        
    lcd.print("Innensensor");
    return;
  }
    if (isnan(h_aussen) || isnan(t_aussen)) {
    Serial.println(F("Keine Daten: Aussensensor"));
    lcd.clear();
    lcd.setCursor(0,0);                                                        
    lcd.print("Keine Daten");
    lcd.setCursor(0,1);                                                        
    lcd.print("Aussensensor");
    return;
  }


// Ende Sensor


  absolut_aussen = (((0.000002*pow(t_aussen,4))+(0.0002*pow(t_aussen,3))+(0.0095*pow(t_aussen,2))+(0.337*t_aussen)+4.9034)*h_aussen)/100; // Berechnung der absoluten Luftfeuchtigkeit aussen
  absolut_innen = (((0.000002*pow(t_innen,4))+(0.0002*pow(t_innen,3))+(0.0095*pow(t_innen,2))+(0.337*t_innen)+4.9034)*h_innen)/100; // Berechnung der absoluten Luftfeuchtigkeit innen

  
  lcd.setCursor(0,0);          
  lcd.print("I ");            
  lcd.print(t_innen,1);        
  lcd.print("\337C ");        
  lcd.print(h_innen,0);        
  lcd.print("% ");
  lcd.print(absolut_innen,1);
  lcd.print("g");


}

HotSystems

Was genau heißt, du bekommst es nicht zum Laufen ?

Gibt es keine Fehlermeldung ?
Wenn doch, welche ?
Evtl. alle Ausgaben in den Einstellungen der IDE aktivieren.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

michael_x

Wenn der RAM knapp ist, (beim UNO mit SD) sollte man zunächst auf String und andere dynamische Speicherfresser verzichten, und die vielen festen Texte alle auf das F-Makro umstellen.

Schau mal, ob das und (erstmal nur zum Test) das Weglassen dieser zwei Zeilen
Code: [Select]
  String Uhrzeit = "";                                                        // für 3 Sekunden
  Uhrzeit = (String(now.day())) + "." + now.month() + "." + now.year() + " " + now.hour() + ":" + now.minute() ;       // auf dem LCD
schon hilft. Falls ja, kann man das auch (für den arduino) erheblich einfacher schreiben. ( Die Operation String + Text ist sehr aufwendig! )

Du meinst außerdem bestimmt
const char SetupDatei[] = "setup.csv"; 


ArdunioArti

Was genau heißt, du bekommst es nicht zum Laufen ?
Der Sketch funktioniert und kann auch Daten von der SD karte laden solange das Keypad nicht initialisiert wird.

Sobald ich über die Zeile
Keypad_I2C i2cKeypad( makeKeymap(tastenLayout), zeilenPins, spaltenPins, anzZeilen, anzSpalten, I2CADDR);

Das Keypad einbinde kommt die Infomeldung bezüglich des Arbeitsspeichers.
Die SD Karte wird zwar noch initialisiert, aber die Datei auf der Karte kann nicht ausgelesen werden.
Folgender Else-Befehl (welcher für den Fall gedacht ist,dass die Karte nicht gelesen werden kann) wird ausgeführt.
Code: [Select]
  } else {
    // if the file didn't open, print an error:
    Serial.println("Laden der Setupdatei fehlgeschlagen");
    lcd.clear();
    lcd.setCursor(0,0);                                                       
    lcd.print("Laden Setupdatei");
    lcd.setCursor(0,1);                                                       
    lcd.print("fehlgeschlagen");
    delay(2000);
  }


Danach läuft der Sketch auch weiter durch. Es funktioniert also nur das Lesen von der SD Karte nicht.
Laut Anleitung des Datenloggers werden die Pins 10 bis 13 für die SD Karte benötigt. Kann es sein das es hier zu einer Doppelnutzung mit dem I2C des Keypads kommt. Aber wenn ich das Keypad ja über den I2C ansteuere dürfte das ja kein Problem sein, oder ?

ArdunioArti

Wenn der RAM knapp ist, (beim UNO mit SD) sollte man zunächst auf String und andere dynamische Speicherfresser verzichten, und die vielen festen Texte alle auf das F-Makro umstellen.

Schau mal, ob das und (erstmal nur zum Test) das Weglassen dieser zwei Zeilen
Code: [Select]
  String Uhrzeit = "";                                                        // für 3 Sekunden
  Uhrzeit = (String(now.day())) + "." + now.month() + "." + now.year() + " " + now.hour() + ":" + now.minute() ;       // auf dem LCD
schon hilft. Falls ja, kann man das auch (für den arduino) erheblich einfacher schreiben. ( Die Operation String + Text ist sehr aufwendig! )

Ich habe jetzt die Zeilen
Code: [Select]
  //String Uhrzeit = "";                                                        // für 3 Sekunden
  //Uhrzeit = (String(now.day())) + "." + now.month() + "." + now.year() + " " + now.hour() + ":" + now.minute() ;       // auf dem LCD
  //lcd.setCursor(0,1);                                                        // angezeigt
  //lcd.print(Uhrzeit); 


zu Kommentaren gemacht. Der Hinweis bezüglich Arbeitsspeicher kommt immer noch mit genau den gleichen Werten. Ist das so weil nur die global definierten Variablen gezählt werden und für die der Speicherplatz reserviert wird ?

Leider wurde das Problem nicht behoben.


Du meinst außerdem bestimmt
const char SetupDatei[] = "setup.csv"; 
Das verstehe ich nicht. Warum sollte ich hier char nehmen ?

DrDiettrich

Ich vermute, daß die Keyboard Bibliothek das Keyboard mit Timer Interrupts pollt, was die Ansteuerung der übrigen Hardware beeinträchtigt. Gibt es eine Möglichkeit, das Keyboard während der SPI und I2C Kommunikation abzuschalten?

postmaster-ino

#7
Dec 25, 2019, 07:30 pm Last Edit: Dec 25, 2019, 07:33 pm by postmaster-ino
Hi

Im Eingangspost schreibt der TO, daß das keyboard über einen PCF8574T (am Datalogger-Shield) angeschlossen ist.
Der hat einen Interrupt-Pin, falls sich was ändert - alternativ könnte man (alle Nase lang) per I²C dort die Pegel abfragen, aber groß Platz für einen Timer sehe ich eher nicht - man müsste Mal in die Lib rein schauen - Link?

Wer lesen kann ... äh ... gefunden (im Eingangspost in einem der Links verlinkt):
https://github.com/joeyoung/arduino_keypads

MfG

ArdunioArti

Hallo zusammen,

vielen dank für die hilfreichen Tipps. Nachdem ich die ganzen Ausgaben auf dem LCD und dem Serial auskommentiert habe funktioniert es. Es ist also wohl wirklich ein Speicherproblem.

Ich werde jetzt die ganzen Ausgaben mittels F-Makro erledigen und versuchen die String so gut es geht zu vermeiden.

Vielen Dank an alle für Eure Hilfe

Go Up