Funktionsnachbau funktioniert nicht (MAX6675)

Hallo,

ich wollte versuchen ob ich es selbst schaffe eine Funktion vom Renesas R8C13 auf den Arduino zu nutzen. Scheinbar nicht. :roll_eyes:

Original Code vom R8C13 sieht so aus:

// Der MAX6675 wird ausgelesen und der 12-Bit-Wert zurückgegeben ********
// P3 = x x x x x CS SCK SO
// max_reg=0 b11 b10 b9 b8 b7 b6 b5 / b4 b3 b2 b1 b0 tco 0 0
unsigned int read_MAX6675_P32 (void)
{
  int i;
  unsigned int data;
  data=0;
  p3_2=0;				            	// CS=Low Port 3.2
  for(i=0;i<16;i++)
  {
    wait_us(100);					// warte 100us
	p3_1=1;					// SCK=High
    wait_us(100);					// warte 100us
    data=((data<<1)|p3_0);			// schiebe nach links und lies SO
    p3_1=0;					// SCK=Low
  }
  wait_us(100);
    p3_2=1;         				// CS=High
  wait_us(100);					// warte 100us
  return (data>>3);				// gib 12-Bit Wert zurück
}

Aufruf mit: t=read_MAX6675_P32();
und vorherige Deklaration mit: unsigned int read_MAX6675_P32 (void);

Nun wollte ich das umbauen und anpassen:

//  Arduino Mega 2560

// Port-Pins definieren
int    MAX_CS = 24;               // Arduino Pin, SPI ChipSelect, 1. MAX6675
int    MAX_SO  = 26;              // Arduino Pin, SPI Datenleitung
int    MAX_CLK = 28; 	          // Arduino Pin, SPI Clockleitung

// Deklaration Datentypen und Variablen
unsigned int TempMAX;				// Zwischenspeicher

void setup() {

  Serial.begin(9600); 

  pinMode(MAX_CS, OUTPUT);
  pinMode(MAX_SO, INPUT);
  pinMode(MAX_CLK, OUTPUT);
  
  digitalWrite(MAX_CS, HIGH);                // Ruhezustand
  digitalWrite(MAX_CLK, LOW);               // Ruhezustand
  
  // Deklaration der Funktionen
  unsigned int read_MAX6675();
  
}

void loop() {
  
  delay(1000);
  TempMAX = read_MAX6675()+2/4;    // Temperaturwert vom MAX6675 einlesen
  Serial.println(TempMAX);
  

}

// -----------------------------------------------------------------------------------------------------	 
// Der MAX6675 wird ausgelesen und der 12-Bit-Wert zurückgegeben ********
unsigned int read_MAX6675 ()
{
  int i;
  unsigned int data;
  data = 0;
  digitalWrite(MAX_CS, LOW);            // CS=Low
  for(i=0;i<16;i++)
    {
     delayMicroseconds(100);             // warte 100us
     digitalWrite(MAX_CLK,HIGH);	 // SCK=High
     delayMicroseconds(100);		 // warte 100us
     // data = ((data<<1) | MAX_SO);	 // schiebe nach links und lies SO
     data = ((data<<1) | digitalRead(MAX_SO));	 // schiebe nach links und lies SO
     digitalWrite(MAX_CLK, LOW);	 // SCK=Low
    }
  delayMicroseconds(100); 	
  digitalWrite(MAX_CS, HIGH);         	 // CS=High
  delayMicroseconds(100); 		 // warte 100us
  return (data>>3);			 // gib 12-Bit Wert zurück
}

Was ist falsch? Ich erhalte irgendwelche Werte um 84 bei Raumtemp. usw. Mit Fühler anfassen erhalte ich 127 usw.

Hallo,

es lies mir keine Ruhe. :slight_smile:

Ich habe natürlich nur die Rohwerte erhalten. Das geteilt durch 4 und man hat °C.

TempMAX = read_MAX6675()/4; // Temperaturwert vom MAX6675 einlesen

Die Zeile hier, wie schreibt die ein Profi? Sieht etwas komisch aus, scheint aber zu funktionieren
data = ((data<<1) | digitalRead(MAX_SO)); // schiebe nach links und lies SO

Die Funktiondeklaration, gehört die richtigerweise in setup oder davor?

Auf dem Arduino brauchst du keine Funktions-Prototypen zu deklarieren. Das übernimmt die IDE für dich im Hintergrund. Deshalb kann man Funktionen verwenden bevor man sie deklariert und damit überall hinschreiben. Wenn überhaupt müsste das global geschehen.

data = ((data<<1) | digitalRead(MAX_SO));

Das schiebt data um eins nach links um Platz für das ausgelesene Bit zu machen, das dann mit dem Oder auf Bit 0 geschrieben wird.

Hallo,

Danke. Wieder etwas gelernt. :slight_smile:

Nochwas.

Wenn ich die Variable "Temp" als float deklariere, warum erhalte ich dann immer noch .00 nach dem Komma. Statt ein vielfaches von 0.25 ?
Wenn ich zum Test die gesamte Funktion als float deklariere funktioniert das wie gewünscht. Wäre aber übertrieben, weil der Rohwert nur Ganzzahlig sein kann.

//  Arduino Mega 2560

// Deklaration der Funktionen, übernimmt die Arduino IDE selbst
// unsigned int read_MAX6675();
  
//  Arduino Mega 2560

// Port-Pins definieren
int    MAX_CS = 24;               // Arduino Pin, SPI ChipSelect, 1. MAX6675
int    MAX_SO  = 26;              // Arduino Pin, SPI Datenleitung
int    MAX_CLK = 28; 	          // Arduino Pin, SPI Clockleitung

// Deklaration Datentypen und Variablen
float Temp;		  // Zwischenspeicher

void setup() {

  Serial.begin(9600); 

  pinMode(MAX_CS, OUTPUT);
  pinMode(MAX_SO, INPUT);
  pinMode(MAX_CLK, OUTPUT);
  
  digitalWrite(MAX_CS, HIGH);               // Ruhezustand
  digitalWrite(MAX_CLK, LOW);               // Ruhezustand
  
  // Deklaration der Funktionen
  unsigned int read_MAX6675();
  
}

void loop() {
  
  delay(1000);
  Temp = read_MAX6675()/4;    // Temperaturwert vom MAX6675 einlesen
  Serial.println(Temp);
  

}

// -----------------------------------------------------------------------------------------------------	 
// Der MAX6675 wird ausgelesen und der 12-Bit-Wert zurückgegeben ********
unsigned int read_MAX6675 ()
{
  int i;
  unsigned int data;
  data = 0;
  digitalWrite(MAX_CS, LOW);            // CS=Low
  for(i=0;i<16;i++)
    {
     delayMicroseconds(100);             // warte 100us
     digitalWrite(MAX_CLK,HIGH);	 // SCK=High
     delayMicroseconds(100);		 // warte 100us
     // data = ((data<<1) | MAX_SO);	 // schiebe nach links und lies SO
     data = ((data<<1) | digitalRead(MAX_SO));	 // schiebe nach links und lies SO
     digitalWrite(MAX_CLK, LOW);	 // SCK=Low
    }
  delayMicroseconds(100); 	
  digitalWrite(MAX_CS, HIGH);         	 // CS=High
  delayMicroseconds(100); 		 // warte 100us
  return (data>>3);			 // gib 12-Bit Wert zurück
}

Weil Divisionen standardmäßig Ganzzahl-Divisionen sind und der Datentyp des Ergebnisses keine Rolle für die Berechnung spielt. Du musst auch in float rechnen, damit da Nachkommastellen rauskommen. Deshalb geht es wenn der Rückgabe-Wert float ist.

Mach das:

temp = read_MAX6675() / 4.0;

Dann wird auch mit Gleitkommazahlen gerechnet. Das ist auch in anderen Sprachen so, nicht nur C.

Wenn man keine Literale hat kann man auch eine der Variablen auf float casten. Das ist hier aber nicht nötig.

Hallo,

aha. Ich hatte in der Zwischenzeit weitergesucht nach Informationen und dann das hier probiert. Funktioniert auch. Gibt es Unterschiede zwischen Deiner Variante und der hier?
Schnelligkeit, Speicherverbrauch ...?

"Temp" muß ich weiterhin als float deklarieren, unabhängig von 4 oder 4.0

Temp = (float) read_MAX6675()/4;    // Temperaturwert vom MAX6675 einlesen

Und wo und wie wird festgelegt wieviele Kommastellen ausgegeben werden? Hatte bei der Serial.Print Beschreibung nichts gelesen. Außer den Formaten. Zufälligerweise erhalte ich 2 Kommastellen.

Das ist die Variante mit dem Cast. Kommt aufs gleiche raus. Eine der Variablen muss float sein und da gibt es diese beiden Möglichkeiten. Das Literal als ".0" zu schreiben wird wohl bevorzugt, aber das ist Geschmackssache. Was der Compiler produziert ist wahrscheinlich exakt gleich.

"Temp" muß ich weiterhin als float deklarieren, unabhängig von 4 oder 4.0

Logisch. Aber der Rückgabe-Wert der Funktion kann ein Integer sein.

Hallo,

okay, vielen Dank für die Erklärungn(en).

Mit den Kommastellen habe ich nun auch gelesen wie das geht. Vorhin irgendwie übersehen. Sorry.