DS18B20 auf Atmega8

Ziel ist es, den DS18B20 auf einem Atmega 8 auslesen und den Wert per Modbus zu senden. Hat hier jemand ein Sketch, der unter 4000 Bytes ist? Hab Dallas Lib alle Beispiele geschaut, passen grad noch so auf den Atmega8, ich muss aber noch einige Taster auswerten und die Modbus Lib ist auch noch drauf. Momentan ohne den DS18B20 hab ich 4kB.

When all the code is in the sketch, what was the total size after compiling ?

The new Arduino IDE 1.5.7 BETA has a new compiler. I was able to shrink the code by 25% with an extra compiler flag.

Ich teste mit diesem Sketch:

#include <OneWire.h>
OneWire  ds(10);  // on pin 10

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
 // fahrenheit = celsius * 1.8 + 32.0;
 // Serial.print("  Temperature = ");
 // Serial.print(celsius);
//  Serial.print(" Celsius, ");
 // Serial.print(fahrenheit);
 // Serial.println(" Fahrenheit");
}

Was kann da noch gelöscht werden?
Da wird die Adresse vom DS18B20 ermittelt, ich würde die auch selber eintragen, wenns viel speicher einnimmt.
Leider kenne ich mich mit dem nicht aus.

skorpi08:
Was kann da noch gelöscht werden?

Sobald Du in Deinem Sketch eine einzige Gleitkommeberechnung drin hast, wird eine ca. 1,4 KB große Gleitkomma-Library zu Deinem Programm dazugelinkt.

Wenn Du in einem Programm ohne Gleitkommarechnungen auskommst, wird das Programm gleich ca. 1,4 KB kleiner.

Temperaturen könnte man z.B. statt als Gleitkommazahl als Integerwert behandeln, z.B. als ganze Zahl “Temperatur in Zehntelgrad” oder bei höheren Anforderungen als ganze Zahl “Temperatur in Hundertstelgrad”.

Dein Temperatursensor macht das intern ja auch: Seine Temperaturen sind intern dargestellt nur 9, 10, 11 oder 12 einzelne Bits und keine Gleitkommazahl.

Mir würde auch reichen wenn es ohne komma wäre.
Also ganze Zahl, 19,5 Grad == 195 oder 1950

Hier wäre der ganze Code, für Atmega8:

3.762 Bytes ohne DS18B20
5.060 Bytes mit DS18B20
Mit Arduino IDE 1.5.7:
Der Sketch verwendet 4.754 Bytes (61%) des Programmspeicherplatzes. Das Maximum sind 7.680 Bytes.
Globale Variablen verwenden 276 Bytes des dynamischen Speichers.

#include <SimpleModbusSlave.h>
#include <OneWire.h>
/* The modbus_update() method updates the holdingRegs register array and checks communication.

   Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 6 request the master will attempt to write to your 
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is 
   limited to its internal buffer which differs between manufactures. 
*/
/***************************************************
 * / Input/output pins
/***************************************************/

#define PIN_TASTER       9
OneWire  ds(A3);  // on pin 10

#define ON  8
#define OFF 7

#define BUTTON_DEBOUNCE_DELAY 200
long lastDebounceTime = 0;

/***************************************************
 * / Modbus globals
/***************************************************/
#define MB_TXENPIN   A2
#define MB_SLAVE_ID  1
#define MB_BAUDRATE  9600
#define MB_PARITY  SERIAL_8N2
/*   Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
*/

//////////////// registers of your slave ///////////////////
enum 
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  celsius,
  Licht,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 6 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 6 register array
////////////////////////////////////////////////////////////

void setup()
{
    // configure pins
  pinMode(PIN_TASTER, INPUT);
  pinMode(ON, OUTPUT);  
  pinMode(OFF, OUTPUT); 
  
  modbus_configure(&Serial, MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID, MB_TXENPIN, HOLDING_REGS_SIZE, holdingRegs);
  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID);

}

void loop()
{
 
 byte i;
  byte present = 0;
  byte type_s =0;
  byte data[12];
  byte addr[8] = {0x28, 0x8F, 0x34, 0x85, 0x04, 0x00, 0x00, 0x8D};
  float celsius, fahrenheit;


  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
 present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  
  
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
    modbus_update();
  
   if ((digitalRead(PIN_TASTER) == HIGH) && ((millis() - lastDebounceTime) > BUTTON_DEBOUNCE_DELAY))
  {
    // invert LED state
    holdingRegs[Licht] = !holdingRegs[Licht];

    lastDebounceTime = millis();
  }

    if (holdingRegs[Licht]==1){
      // ON //
  digitalWrite(ON,1);
  digitalWrite(OFF,0);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0);
} 
  else{
    // OFF //
  digitalWrite(ON,0);
  digitalWrite(OFF,1);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0); 
}

}

Da ist immer noch mit Serial.print, wie kann man es ohne dem machen?

skorpi08: Mir würde auch reichen wenn es ohne komma wäre. Also also ganze Zahl, 19,5 Grad == 195 oder 1950

Also ich sehe nur eine einzige Gleitkommadivision in Deinem Code:

celsius = (float)raw / 16.0;

Deine Division durch 16 ist quasi eine Multiplikation mit 0.0625, weil 1/16=0.0625

Daher kannst Du die Temperatur ganz einfach als "long" Wert in Zehntausendstel Grad bekommen, wenn Du Deinen raw-Wert mit 625 multiplizierst.

long celsius10000= raw*625L;

Also 19,5°C wären dann 195000 als long. Mit der richtigen Rundung und einer Integer-Division durch ein Vielfaches von 10 kannst Du die Zehntausendstel Grad dann auch wieder runterrechnen auf einen Integer in Zehntelgrad oder Hundertstelgrad. Und das Programm sollte deutlich kleiner als vorher sein, weil die Math-Library für Gleitkommaarithmetik nicht mit eingebunden werden braucht.

Auch wenn ich

float celsius;
celsius = (float)raw / 16.0;

auskommentiere, bleibts bei 5060 Bytes

Mit der Arduino IDE 1.5.7 kann ich wohl nicht über USBasp uploaden. Steht als Fehler:

Fehler beim Hochladen: Fehlender Konfigurationsparameter 'upload.tool'

skorpi08:
Auch wenn ich

float celsius;

celsius = (float)raw / 16.0;




auskommentiere, bleibts bei 5060 Bytes

Du bindest ja auch noch eine Third-Party Magic-Library ein:

#include <SimpleModbusSlave.h>

Wie sieht es denn in dieser Library mit Gleitkommazahlen aus?

Gute Frage, hab mich damit nicht befasst.
Dann wirds wohl schon da genutzt.

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
 present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }

kann man es nicht ohne delay machen?
Wozu ist present? Habs mal gelöscht, wird aber wohl für noch irgendwas gebraucht. Dacht ist einfach nur ne anzeige für Serial.print(" Data = ");.

skorpi08: kann man es nicht ohne delay machen?

Natürlich kannst Du auch einen DS18B20 auch ohne delay abfragen.

Aber Du mußt ihm trotzdem Zeit zum Messen geben. Mindestens 750 Millisekunden pro Messung (oder etwas mehr).

Dazu müßtest Du den Messvorgang dann in zwei Vorgänge aufteilen: 1.) Messung vom Sensor anfordern 2.) Nach frühestens 750 ms (oder etwas mehr): Messwert abholen

Was Du in den 750 Millisekunden dazwischen machst, ist dem Sensor egal. Du kannst das Programm entweder für die Zeit mit delay() blockieren. Oder irgendwas anderes machen. Aber Du kannst den angeforderten Messwert nicht vom Sensor abholen, bevor der Sensor nicht mit der angeforderten Messung fertiggeworden ist.

Nachtrag noch wegen der scheinbar gleichbleibenden Dateigröße: Die zusätzlich eingebundene Library scheint keine Gleitkommarechnungen durchzuführen, aber Du in Deinem Test-Sketch hast zwar die Berechnung hingeschrieben:

celsius = (float)raw / 16.0;

aber der so errechnete Wert wird im Programm hinterher nirgends mehr verwendet! Dadurch optimiert der Compiler dann natürlich die Berechnung weg, und wenn er feststellt, dass keine Gleitkommarechnung notwendig ist, weil diese wegoptimiert wurde, wird dann auch kein Gleitkommacode mehr ins Programm eingebunden.

Du mußt den Wert auch tatsächlich verwenden und zum Beispiel auf Serial ausgeben, damit die Rechnung NICHT aus dem Code wegoptimiert wird. Also z.B.:

celsius = (float)raw / 16.0;
Serial.println(celsius);

Dann kann die Rechnung nicht wegoptimiert werden und dann wird auch die Gleitkomma-Library automatisch mit in den Code eingebunden.

Eigentlich dachte ich dass der Wert über Modbus gesendet wird?!

//////////////// registers of your slave ///////////////////
enum 
{     
  celsius,
  Licht,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 6 share the same register array
  // i.e. the same address space
};

Alles was bei enum drin steht, wird auch übertragen. Somit wäre der Wert auch in "Verwendung".

skorpi08: Eigentlich dachte ich dass der Wert über Modbus gesendet wird?!

//////////////// registers of your slave ///////////////////
enum 
{     
  celsius,
  Licht,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 6 share the same register array
  // i.e. the same address space
};

Alles was bei enum drin steht, wird auch übertragen. Somit wäre der Wert auch in "Verwendung".

???

Deine obenstehende enum-Definition ist eine Umschreibung für sowas:

//////////////// registers of your slave ///////////////////
#define  celsius 0
#define  Licht 1
#define  HOLDING_REGS_SIZE 2

Das Aufzählungskonstante "celsius" hat mit der später in der loop-Funktion deklarierten Gleitkomma-Variablen celsius nichts zu tun. Das kannst Du auch testen, indem Du mal die eine oder andere "celsius" Deklaration vom Namen her änderst.

Naja, etwas falsch ausgedrückt. So wäre es korrekter: holdingRegs[celsius] == celsius;

Hab grad Problem mit der Übertragung, kommen ständig Fehler obwohl nix übertragen werden sollte

mit

long celsius1= raw*625L;
holdingRegs[celsius] =celsius1;

5.144 Bytes
bekomme ich

18:37:13.178 INFO runtime.busevents[:26] - Light_GF_Corridor_Wardrobe state updated to OFF
18:37:13.178 INFO runtime.busevents[:26] - Temperature_GF_Corridor state updated to 10981
18:37:14.233 INFO runtime.busevents[:26] - Light_GF_Corridor_Ceiling state updated to OFF

Wenn man mit dem Finger auf dem DS18B20 drauf hält, steigt die Zahl.

mit

float celsius1;
celsius = (float)raw / 16.0;
holdingRegs[celsius] =celsius1;

5.718 Bytes
bekomme ich

18:38:52.016 INFO runtime.busevents[:26] - Light_GF_Corridor_Wardrobe state updated to OFF
18:38:52.017 INFO runtime.busevents[:26] - Temperature_GF_Corridor state updated to 27
18:38:53.069 INFO runtime.busevents[:26] - Light_GF_Corridor_Ceiling state updated to OFF

Hier bleibt es allerdings durchgehend bei 27.

mit

  long celsius1= raw / 16;
  holdingRegs[celsius] =celsius1;

bekomme ich 22

19:31:04.125 INFO runtime.busevents[:26] - Temperature_GF_Toilet state updated to 22
19:31:05.174 INFO runtime.busevents[:26] - Light_GF_Corridor_Ceiling state updated to OFF
19:31:05.731 INFO runtime.busevents[:26] - Light_GF_Corridor_Wardrobe state updated to OFF
19:31:05.731 INFO runtime.busevents[:26] - Temperature_GF_Corridor state updated to 65267

Hab ichs richtig mit dem delay für den DS18B20 gemacht?

#include <SimpleModbusSlave.h>

/* The modbus_update() method updates the holdingRegs register array and checks communication.

   Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 6 request the master will attempt to write to your 
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is 
   limited to its internal buffer which differs between manufactures. 
*/
/***************************************************
 * / Input/output pins
/***************************************************/
#include <OneWire.h>
OneWire  ds(A3);  // on pin 10
#define PIN_TASTER       9

#define ON  8
#define OFF 7

#define BUTTON_DEBOUNCE_DELAY 900
long lastDebounceTime = 0;

/***************************************************
 * / Modbus globals
/***************************************************/
#define MB_TXENPIN   A2
#define MB_SLAVE_ID  2
#define MB_BAUDRATE  9600
#define MB_PARITY  SERIAL_8N2
/*   Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
*/

//////////////// registers of your slave ///////////////////
enum 
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  Licht,
celsius,   
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 6 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 6 register array
////////////////////////////////////////////////////////////

void setup()
{
    // configure pins
  pinMode(PIN_TASTER, INPUT);
  pinMode(ON, OUTPUT);  
  pinMode(OFF, OUTPUT); 
  
  modbus_configure(&Serial, MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID, MB_TXENPIN, HOLDING_REGS_SIZE, holdingRegs);
  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID);

}

void loop()
{  
  
    modbus_update();
  byte i;
  byte present = 0;
  byte type_s =0;
  byte data[12];
  byte addr[8] = {0x28, 0x97, 0xCC, 0x84, 0x04, 0x00, 0x00, 0x60};
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
//  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  if (((millis() - lastDebounceTime) > BUTTON_DEBOUNCE_DELAY))
  {
 present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
  Serial.print(present,HEX);
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
  }

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  float celsius1;
celsius1 = (float)raw / 16.0;
  //long celsius1= raw*625L;
  holdingRegs[celsius] =celsius1;
  }

  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
  
  
   if ((digitalRead(PIN_TASTER) == HIGH) && ((millis() - lastDebounceTime) > BUTTON_DEBOUNCE_DELAY))
  {
    // invert LED state
    holdingRegs[Licht] = !holdingRegs[Licht];

    lastDebounceTime = millis();
  }

    if (holdingRegs[Licht]==1){
      // ON //
  digitalWrite(ON,1);
  digitalWrite(OFF,0);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0);
} 
  else{
    // OFF //
  digitalWrite(ON,0);
  digitalWrite(OFF,1);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0); 
}

}

Kann man hier das Serial.print irgendwie rausnehmen? oder stört es bei der Übertragung nicht?

 present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
  Serial.print(present,HEX);
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
  }

skorpi08: mit

long celsius1= raw*625L;
holdingRegs[celsius] =celsius1;

Wie wäre es denn damit, symbolische Konstanten stets in GROSSBUCHSTABEN zu schreiben, und das bei enum-Konstanten genau so wie bei #define-Konstanten zu handhaben, damit Du nicht zwischen Konstantennamen und Variablennamen durcheinander kommst?

//////////////// registers of your slave ///////////////////
enum 
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  CELSIUS,
  LICHT,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 6 share the same register array
  // i.e. the same address space
};

Dann kommt man beim Schreiben von Code nicht so leicht durcheinander, wo eine symbolische Konstante und wo eine Variable verwendet wird.

skorpi08: Hab ichs richtig mit dem delay für den DS18B20 gemacht?

Keine Ahnung, ich finde, es sieht irgendwie merkwürdig aus.

skorpi08: Hier bleibt es allerdings durchgehend bei 27.

Dass Dein Register-Array als Integer-Array deklariert ist, ist dir aber schon klar:

unsigned int holdingRegs[HOLDING_REGS_SIZE];

Oder? Und wenn Du eine Gleitkommazahl an einen Integer-Wert zuweist, bekommt der Integer nur den ganzzahligen Anteil. Also überträgst Du so wie Du es machst auch stets nur einen Integer-Wert, nämlich die Vorkommastellen der Temperatur.

Vielleicht doch die Temperatur lieber als Integer in Zehntelgrad übertragen?

Es ging mir erstmal nur um die Werte, habe hier ja keine 27 Grad oder mehr.

  long celsius1= raw / 16;
  holdingRegs[celsius] =celsius1;

5.524 Bytes

Damit komme ich auf 22 Grad, kommt eher hin.

Kann ich noch ein Register Array erstellen mit enum?

enum 
{     
CELSIUS,   
  HOLDING_REGS_SIZE_2 // leave this one
};

long holdingRegs[HOLDING_REGS_SIZE_2]; // function 3 and 6 register array

Bei enums werden den Konstanten Werte von 0 bis n zugewiesen. In dem Fall hat HOLDING_REGS_SIZE_2 den Wert 1. Das Array hat damit nur ein Element.

Versteh zwar die Antwort nicht aber jetzt weiß ich wenigstens dass es so nicht geht.

SimpleModbusSlaveArduinodd:71: error: conflicting declaration 'long int holdingRegs [1]' SimpleModbusSlaveArduinodd:59: error: 'holdingRegs' has a previous declaration as 'unsigned int holdingRegs [1]'

skorpi08: Kann ich noch ein Register Array erstellen mit enum?

Ja klar kannst Du, das ergibt sich doch aus den Kommentaren in dem von Dir kopierten Code.

Aber um eine Gleitkommazahl (4 Bytes) in Integer-Registern zu übertragen, benötigst Du zwei Stück von der Sorte.

Zum Beispiel:

enum 
{     
  CELSIUSHIWORD,   
  CELSIUSLOWORD,
  HOLDING_REGS_SIZE_2 // leave this one
};

Dann teilst Du vor dem Senden Deinen 4-Byte Gleitkommawert auf zwei Register auf:

holdingRegs[CELSIUSHIWORD]= obere zwei Bytes der Variablen holdingRegs[CELSIUSLOWORD]= untere zwei Bytes der Variablen

Und am Ende mußt Du die Bytes zu zwei und zwei dann wieder zu einer float-Gleitkommazahl zusammenfügen und kannst sie Dir danach anzeigen lassen.

Wenn, dann welche Auswirkungen könnte es haben wenn ich von int auf long ändere?

long holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 6 register array

Wie ichs verstehe, würd sich eigentlich nix ändern, ausser dass ich die Lib alles auf long ändern müsste.
Mehr Bytes würds wahrscheinlich einnehmen.

Welches wäre für mich relevant, vor oder nach der ersten else?

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }

Wie teilt man sowas, noch nie gemacht?!

Aber auch wenn ichs geteilt übermittelt kriege, weiß ich immer noch nicht wie ichs in openHAB flicke.