Go Down

Topic: Arduino lest immer 0 aus RS485 Verbindung (Read 1 time) previous topic - next topic

dasrogl

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;   
    }
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

michael_x

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



dasrogl

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;
  }
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

HotSystems

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.
Gruß Dieter

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

dasrogl

Wie soll ich das machen?  Da es ModBus RTU ist spuckt mir der Serielle Monitor nur Sonderzeichen aus
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

HotSystems

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.

Gruß Dieter

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

michael_x

So z.B. sollte sollten die binären "Sonderzeichen" lesbar sein:

Serial.println((uint16_t)au16data[8], HEX);

dasrogl

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.
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

michael_x

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.

dasrogl

#9
Aug 06, 2016, 01:04 pm Last Edit: Aug 06, 2016, 01:29 pm by dasrogl
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
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

michael_x

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 ;)

dasrogl

0 und -1 gefällt mir nicht  :) .  Wenn ich den Slave mit einem RS485 zu USB Adapter betribe zeigt er mir andere Werte an!
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

michael_x

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
?

dasrogl

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
Was bekommt ein Kondensator zu Weihnachten? Ein Farad.

michael_x

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?

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


Go Up