Arduino Forum

International => Deutsch => Topic started by: dasrogl on Aug 01, 2016, 11:39 am

Title: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 01, 2016, 11:39 am
Hallo, ich habe das Problem, dass ein Register immer mit 0 ausgelesen wird, obwohl sich nicht 0 darin befindet. Ich hoffe ihr könnt mir helfen.

Code: [Select]
#include <ModbusRtu.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/*  Modbus object declaration
    node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
              or any pin number > 1 for RS-485 */
 
Modbus master(0,0,2); // this is master and RS-232 or USB-FTDI
modbus_t telegram[4];
unsigned long u32wait;
uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
int sprayungen;
int kg;
int kali;
int schalter;
int a = 0;
int maxwert ;
int zeithilfe;
int tasterplusZeit;
int tasterplusGedrueckt;
int tasterminusZeit;
int tasterminusGedrueckt;

//                    addr, en,rw,rs,d4,d5,d6,d7,bl,backlight-polarity
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 3, 4, 5, 6, 7, POSITIVE);

void setup() {
  lcd.begin(16, 2);
  lcd.backlight();
//         (Zeichen, Zeile)
    lcd.setCursor(0,0);
 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
 
  // telegram 0: read registers
  telegram[0].u8id = 3; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 0; // start address in slave
  telegram[0].u16CoilsNo = 6; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino

 //telegram 1: write a single register
  telegram[1].u8id = 1; // slave address
  telegram[1].u8fct = 6; // function code (this one is write a single register)
  telegram[1].u16RegAdd = 0; // start address in slave
  telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[1].au16reg = au16data+6  ; // pointer to a memory array in the Arduino

  telegram[2].u8id = 1; // slave address
  telegram[2].u8fct = 3; // function code (this one is registers read)
  telegram[2].u16RegAdd = 1; // start address in slave
  telegram[2].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[2].au16reg = au16data+7;
   
  telegram[3].u8id = 2; // slave address
  telegram[3].u8fct = 6; // function code (this one is registers read)
  telegram[3].u16RegAdd = 1; // start address in slaven
  telegram[3].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[3].au16reg = au16data+8; // pointer to a memory array in the Arduino
 
  master.begin( 115200 );
  master.setTimeOut( 2000 ); // if there is no answer in 1000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0;

}

void loop(){


  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
  u8query++;
  if (u8query > 10) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {  //IDLE = Leerlauf   
      u8state = 0;
      u32wait = millis() + 1000;
    }
    break;
  }
     master.poll();
  digitalWrite(3, au16data[0]);   //LED(3)
  digitalWrite(4, au16data[1]);
  digitalWrite(5, au16data[2]);
  digitalWrite(6, au16data[3]);
  digitalWrite(7, au16data[4]);
  digitalWrite(8, au16data[5]);
 
  au16data[6] = digitalRead(9);  //Sprayer(1)
  sprayungen = au16data[7]; //Spray-Zaehler
  master.query(telegram[3]);
  kg = au16data[8];               //Waegezelle(2)
   if(digitalRead(10) == HIGH){
    tasterplusZeit = millis();     
    tasterplusGedrueckt = 1;       
  }     
 
  if((millis() - tasterplusZeit > 100) && tasterplusGedrueckt == 1){
    master.query(telegram[3]);
    //  telegram[3].u8fct = 6;
      int a = au16data[9];
      au16data[8] = a + 1;
      master.poll();
     // telegram[3].u8fct = 3;             
      tasterplusGedrueckt = 0;     
    }

     if(digitalRead(11) == HIGH){
    tasterminusZeit = millis();   
    tasterminusGedrueckt = 1;     
  }
 
  if((millis() - tasterminusZeit > 100) && tasterminusGedrueckt == 1){
     // telegram[3].u8fct = 6;
     master.query(telegram[3]);
      int a = au16data[9];
      au16data[8] = a - 1;
      master.poll();
     // telegram[3].u8fct = 3;             
      tasterminusGedrueckt = 0;   
    }
 
  if(digitalRead(12) == HIGH){  //Tare
   // telegram[3].u8fct = 6;
    au16data[10] = 1;
    master.poll();
    //telegram[3].u8fct = 3 ;
  }

  if(kg >= maxwert){
    maxwert = kg;
    zeithilfe = millis();
  }
  if(millis() - zeithilfe > 15000 && kg <= maxwert){
    maxwert = 0;
    zeithilfe = millis();
  }
   
  //LCD
  //lcd.clear();
  lcd.setCursor(0,0);

  if(stellen(kg) == 1){   //KG(derzeit)
    lcd.print("  ");
  }
  else if(stellen(kg) == 2){
    lcd.print(" ");
  }
  lcd.print(kg);
  lcd.print("kg");
  lcd.print("  max:");
 

  if(stellen(maxwert) == 1){   //KG(max)
    lcd.print("  ");
  }
  else if(stellen(maxwert) == 2){
    lcd.print(" ");
  }
  lcd.print(maxwert);
  lcd.print("kg");
  lcd.setCursor(0,1);

 
  if(stellen(sprayungen) == 1){  //Sprayungen
    lcd.print("    ");
  }
  else if(stellen(sprayungen) == 2){
    lcd.print("   ");
  }
  else if(stellen(sprayungen) == 3){
    lcd.print("  ");
  }
  else if(stellen(sprayungen) == 4){
    lcd.print(" ");
  }                                                 
  lcd.print(sprayungen);
  lcd.print(" Sprayungen");   
}


  int stellen(int x){
    if ( x < 10 )
      return 1;
    else if ( x < 100 )
      return 2;
    else if ( x < 1000 )
      return 3;
    else if ( x < 10000)
      return 4;
  }


Bei diesem Codestück habe ich das Problem das int a immer = 0 ist. Ich habe es getestet, dass mein Slave nicht 0 ins Register schreibt

Code: [Select]
   if(digitalRead(10) == HIGH){
    tasterplusZeit = millis();     
    tasterplusGedrueckt = 1;       
  }     
 
  if((millis() - tasterplusZeit > 100) && tasterplusGedrueckt == 1){
    master.query(telegram[3]);
    //  telegram[3].u8fct = 6;
      int a = au16data[9];
      au16data[8] = a + 1;
      master.poll();
     // telegram[3].u8fct = 3;             
      tasterplusGedrueckt = 0;     
    }

     if(digitalRead(11) == HIGH){
    tasterminusZeit = millis();   
    tasterminusGedrueckt = 1;     
  }
 
  if((millis() - tasterminusZeit > 100) && tasterminusGedrueckt == 1){
     // telegram[3].u8fct = 6;
     master.query(telegram[3]);
      int a = au16data[9];
      au16data[8] = a - 1;
      master.poll();
     // telegram[3].u8fct = 3;             
      tasterminusGedrueckt = 0;   
    }
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 01, 2016, 11:46 am
Du hast 2 variable namens a, beide vom Datentyp int.


Hab deinen Code nicht genau angesehen, aber ...

      int   a = au16data[9]; // lass hier das int mal weg


Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 01, 2016, 11:51 am
Ich habe die variable a nun durch b und c ersetzt, jedoch habe ich das selbe Problem noch immer

Code: [Select]

#include <ModbusRtu.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/*  Modbus object declaration
    node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
              or any pin number > 1 for RS-485 */
 
Modbus master(0,0,2); // this is master and RS-232 or USB-FTDI
modbus_t telegram[4];
unsigned long u32wait;
uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
int sprayungen;
int kg;
int kali;
int schalter;
int a = 0;
int b;
int c;
int maxwert ;
int zeithilfe;
int tasterplusZeit;
int tasterplusGedrueckt;
int tasterminusZeit;
int tasterminusGedrueckt;

//                    addr, en,rw,rs,d4,d5,d6,d7,bl,backlight-polarity
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 3, 4, 5, 6, 7, POSITIVE);

void setup() {
  lcd.begin(16, 2);
  lcd.backlight();
//         (Zeichen, Zeile)
    lcd.setCursor(0,0);
  
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
 
  // telegram 0: read registers
  telegram[0].u8id = 3; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 0; // start address in slave
  telegram[0].u16CoilsNo = 6; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino

 //telegram 1: write a single register
  telegram[1].u8id = 1; // slave address
  telegram[1].u8fct = 6; // function code (this one is write a single register)
  telegram[1].u16RegAdd = 0; // start address in slave
  telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[1].au16reg = au16data+6  ; // pointer to a memory array in the Arduino

  telegram[2].u8id = 1; // slave address
  telegram[2].u8fct = 3; // function code (this one is registers read)
  telegram[2].u16RegAdd = 1; // start address in slave
  telegram[2].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[2].au16reg = au16data+7;
    
  telegram[3].u8id = 2; // slave address
  telegram[3].u8fct = 6; // function code (this one is registers read)
  telegram[3].u16RegAdd = 1; // start address in slaven
  telegram[3].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[3].au16reg = au16data+8; // pointer to a memory array in the Arduino
  
  master.begin( 115200 );
  master.setTimeOut( 2000 ); // if there is no answer in 1000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0;

}

void loop(){


  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
  u8query++;
  if (u8query > 10) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {  //IDLE = Leerlauf  
      u8state = 0;
      u32wait = millis() + 1000;
    }
    break;
  }
     master.poll();
  digitalWrite(3, au16data[0]);   //LED(3)
  digitalWrite(4, au16data[1]);
  digitalWrite(5, au16data[2]);
  digitalWrite(6, au16data[3]);
  digitalWrite(7, au16data[4]);
  digitalWrite(8, au16data[5]);
  
  au16data[6] = digitalRead(9);  //Sprayer(1)
  sprayungen = au16data[7]; //Spray-Zaehler
  master.query(telegram[3]);
  kg = au16data[8];               //Waegezelle(2)
   if(digitalRead(10) == HIGH){
    tasterplusZeit = millis();    
    tasterplusGedrueckt = 1;      
  }      
  
  if((millis() - tasterplusZeit > 100) && tasterplusGedrueckt == 1){
    master.query(telegram[3]);
    //  telegram[3].u8fct = 6;
       b = au16data[9];
      au16data[8] = b + 1;
      master.poll();
     // telegram[3].u8fct = 3;            
      tasterplusGedrueckt = 0;    
    }

     if(digitalRead(11) == HIGH){
    tasterminusZeit = millis();    
    tasterminusGedrueckt = 1;      
  }
 
  if((millis() - tasterminusZeit > 100) && tasterminusGedrueckt == 1){
     // telegram[3].u8fct = 6;
     master.query(telegram[3]);
      c = au16data[9];
      au16data[8] = c - 1;
      master.poll();
     // telegram[3].u8fct = 3;            
      tasterminusGedrueckt = 0;    
    }
  
  if(digitalRead(12) == HIGH){  //Tare
   // telegram[3].u8fct = 6;
    au16data[10] = 1;
    master.poll();
    //telegram[3].u8fct = 3 ;
  }

  if(kg >= maxwert){
    maxwert = kg;
    zeithilfe = millis();
  }
  if(millis() - zeithilfe > 15000 && kg <= maxwert){
    maxwert = 0;
    zeithilfe = millis();
  }
  
  //LCD
  //lcd.clear();
  lcd.setCursor(0,0);

  if(stellen(kg) == 1){   //KG(derzeit)
    lcd.print("  ");
  }
  else if(stellen(kg) == 2){
    lcd.print(" ");
  }
  lcd.print(kg);
  lcd.print("kg");
  lcd.print("  max:");
  

  if(stellen(maxwert) == 1){   //KG(max)
    lcd.print("  ");
  }
  else if(stellen(maxwert) == 2){
    lcd.print(" ");
  }
  lcd.print(maxwert);
  lcd.print("kg");
  lcd.setCursor(0,1);

  
  if(stellen(sprayungen) == 1){  //Sprayungen
    lcd.print("    ");
  }
  else if(stellen(sprayungen) == 2){
    lcd.print("   ");
  }
  else if(stellen(sprayungen) == 3){
    lcd.print("  ");
  }
  else if(stellen(sprayungen) == 4){
    lcd.print(" ");
  }                                                
  lcd.print(sprayungen);
  lcd.print(" Sprayungen");    
}


  int stellen(int x){
    if ( x < 10 )
      return 1;
    else if ( x < 100 )
      return 2;
    else if ( x < 1000 )
      return 3;
    else if ( x < 10000)
      return 4;
  }
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: HotSystems on Aug 01, 2016, 12:47 pm
Um dieses Problem zu lösen, solltest du an geeigneter Stelle die Inhalte im sweriellen Monitor anzeigen lassen.
Evtl. ist ja auch die Übertragung schon fehlerhaft.
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 01, 2016, 01:01 pm
Wie soll ich das machen?  Da es ModBus RTU ist spuckt mir der Serielle Monitor nur Sonderzeichen aus
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: HotSystems on Aug 01, 2016, 01:20 pm
Ok, da ich ModBus nicht kenne, kann ich dazu nichts sagen
Aber du kannst dir doch den Inhalt anzeigen lassen, wenn er einer Variable übergeben wird.

Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 01, 2016, 02:30 pm
So z.B. sollte sollten die binären "Sonderzeichen" lesbar sein:

Serial.println((uint16_t)au16data[8], HEX);
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 06, 2016, 10:30 am
Entschuldigung, dass ich lange nicht geantwortet habe. Ich war sehr stressig.

mit      Serial.println((uint16_t)au16data[8], HEX); bekomme ich auch nur FFFF. Also 0.
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 06, 2016, 12:28 pm
Mal abgesehen davon, dass 0xFFFF so ungefähr "das Gegenteil" von 0 ist, würde ich mal bei den Telegrammen einzeln schauen, was passiert.

Mirt ist übrigens noch aufgefallen, dass du 4 Telegramme definiert hast  modbus_t telegram[4];


aber dass du 10 verschiedene Telegramme aufrufst

Code: [Select]

    master.query( telegram[u8query] ); // send query (only once)
  ...
  u8query++;
  if (u8query > 10) u8query = 0;


Da greift Arduino gnadenlos irgendwo hin, und nachvollziehen was dann passiert ist erheblich mühsamer, als es richtig zu machen.
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 06, 2016, 01:04 pm
Achso Tschuldige. Hab gedacht weil zuerst 0 und dann FFFF stand, dass das das (nein keine Wortwiederholung  :) ) selbe ist ist. Aber stimmt, ist es nicht 65535 oder so? Ich hab mich noch nie mit dem Hexadezimalsystem beschäftigt.

Die 10 hab ich auf 4 geändert und mein LCD zeigt mir jetzt manchmal 0 und manchmal -1 an
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 06, 2016, 02:27 pm
Quote
ist es nicht 65535 oder so?
Ja, oder -1, wenn man es als vorzeichenbehaftete Zahl interpretiert.

Quote
Die 10 hab ich auf 4 geändert und mein LCD zeigt mir jetzt manchmal 0 und manchmal -1 an
Ok, da ich ModBus nicht kenne, kann ich dazu nichts sagen
Aber du kannst dir doch den Inhalt anzeigen lassen, wenn er einer Variable übergeben wird.
Da sind wir jetzt. Warum dir 0 oder -1 nicht gefällt, musst du selber wissen ;)
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 06, 2016, 02:32 pm
0 und -1 gefällt mir nicht  :) .  Wenn ich den Slave mit einem RS485 zu USB Adapter betribe zeigt er mir andere Werte an!
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 06, 2016, 02:56 pm
Hier hast du die volle Kontrolle. Musst es nur richtig machen. Und bei Modbus Details bin ich leider auch überfragt.

Code: [Select]
telegram[0].u8id = 3; // slave address
...
telegram[1].u8id = 1; // slave address
?
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 06, 2016, 05:05 pm
Du musst es nur richtig machen... Dann bräuchte ich ja kein Forum :smiley-lol:
Meine Einstellungen, mit denen der Slave in qModMaster (ModBus Master Software) funktioniert sind: Slave ID 2, Read Holding Registers, TimeOut = 2000
Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: michael_x on Aug 06, 2016, 06:39 pm
Slave ID : 1 2 oder 3  ?

Guck eventuell auch mal die Library an, ob die nicht Fehler melden würde, die dein Sketch ignoriert...

Oder hast du dieses Problem (http://electronics.stackexchange.com/questions/49097/arduino-as-modbus-master-with-max485-doesnt-get-any-response)?

Der brauchte allerdings ein Oszi, um zu sehen, dass der Modbus Slave dem Arduino gar nicht geantwortet hat. (Falls ich das richtig überflogen habe)

Title: Re: Arduino lest immer 0 aus RS485 Verbindung
Post by: dasrogl on Aug 06, 2016, 06:51 pm
Ich schau nachher mit dem Oszi. Slave 1, 2 und 3  :)  Ich habe drei Slaves, nur dieser funktioniert nicht