ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Der chaotische Hauptfaden

Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese

Antworten
Farbe
Beiträge: 410
Registriert: So 29. Sep 2013, 16:06

ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von Farbe »

Hallo Leute,

ich hab ein problem mit meinem ATtiny.
Ich will eigentlich nur abwechselnd eine Spannung (Batterie status) und die Temperatur messen.
Leider klappt das nicht so recht, irgendwie kommen immer 600k raus -> 326°C ... kann irgendwie nicht sein.
Benutzen tu ich den megaTinyCore.

Code:

Code: Alles auswählen

Setup
// ADC values
unsigned long lastMeasurement = 0;      	    // time ADC mesurement was last taken
int measurementTime = 100;                	    //interval for taking measurements
bool batt = true;                                   	   //wich measurement to take next batt/temp
bool measurement = false;                  	     // measurement in progress

// battery voltage
int battery = 128;							// initial value

// temperature related values
unsigned long temp = 0;						//initial value
int8_t sigrow_offset = SIGROW.TEMPSENSE1; 	    // Read signed value from signature row (calibration)
uint8_t sigrow_gain = SIGROW.TEMPSENSE0;   	   // Read unsigned value from signature row (calibration)

///////////////ADC einstellen///////////////
////////////////////////////////////////////
ADC0.CTRLB = 0b00000001;                              	   //2 sampels accumulation
ADC0.CTRLC |= 0b01000111;                  	           //reduced sampling c, internal vref, /256 clk divider
ADC0.CTRLD = 0b10110001;                      	          //inital sample delay 256, sample delay variation on, 
ADC0.SAMPCTRL = 0b00001111;                	          //sample lenght = 7
ADC0.CTRLA = 0b00000101;                     	           //ADC on, 8bit, single conversion
Loop:

Code: Alles auswählen

if(ADC0.COMMAND == 0b00000000 && measurement == true){           	   // measurement done, process value
        measurement = false;
        if(batt == true){                	     // if this is a battery mesurement process it inside checkBattery
          checkBattery();
        }else{
          checkTemp();                   	     // otherwise process inside checkTemp
        }  
      }

      
      if((millis() - lastMeasurement) >= measurementTime){          	  // check for time up to make a new measurement
      lastMeasurement = millis();                                 	    // save last time mesurement was taken
      	
      if(batt == true){
        
      analogReference(VDD);                                                	     // vref to 5V (VDD) for battery measurment
      ADC0.CTRLA = 0b00000100;                                            	      //ADC off, 8bit, normaler modus
      ADC0.CTRLB = 0b00000001;                                            	      //2 sampels accumulation
      ADC0.MUXPOS = 0b00000111;                                              	   // AIN7 as input (connected to vBatt)
      ADC0.CTRLA = 0b00000101;                                                	  //ADC on, 8bit, normaler modus
      ADC0.COMMAND = 0b00000001;                                        	        //start conversion!
      
      measurement = true;
      
      }else{
        
      analogReference(INTERNAL1V1);
      ADC0.CTRLA = 0b00000000;                                     	             //ADC off, 10bit, normaler modus
      ADC0.CTRLB = 0b00000000;                                     	             //0 sampels accumulation
      ADC0.MUXPOS = 0b00000111;                                  	             // tempsense as input
      ADC0.CTRLA = 0b00000001;                                      	            //ADC on, 10bit, normaler modus
      ADC0.COMMAND = 0b00000001;                                  	            // start conversion!
      
      measurement = true;
      }
      }
      
tempCheck:

Code: Alles auswählen

void checkTemp(){                                          // mesure temperature 
  
  temp = ADC0.RES;
  temp -= sigrow_offset;
  temp *= sigrow_gain;         // Result might overflow 16 bit variable (10bit+8bit)
  temp += 0x80;                // Add 1/2 to get correct rounding on division below 
  temp >>= 8;                  // Divide result to get Kelvin
  temp = (temp-273);             // temp to celsius

  batt = true;                                          // change next measurement value  

}
batteryCheck:

Code: Alles auswählen

void checkBattery(){                                          // mesure battery voltage
  
      battery = ((ADC0.RES-345)*3.65);                       // scale ADC values
      if(battery <= 0){                                      // set value to min if overflow
         battery = 0;
         }
      if(battery >= 255){                                    // set value to max if overflow
         battery = 255;
         }
      
      if(battery <= 1){                                     // ceck if undervoltage, than lockout
      dutyrLED = 0;                                          // setting dutyrLED for flashing
      UVlockout();                                           // go into UVL
      }
      
      batt = false;                                          // change next measurement value  

}

Vielleicht sieht jemand das Problem.

Batteriespannung funktioniert wunderbar, temp ist aber immer 325.

(ich hab den Code aufs wesentliche reduziert, da sind noch andere Funktionen drin, die machen aber alle keine Probleme, nur der Temp Sensor treibt mich seit mehreren Stunden in den Wahnsinn)
Danke
Farbe
Benutzeravatar
sukram
Beiträge: 3116
Registriert: Sa 10. Mär 2018, 18:27
Wohnort: Leibzsch

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von sukram »

Moin. Ich habe jetzt nicht den überblick zu genau dieser Kombination (Tiny0 und Arduino) aber bei den Atmegas war es so, das nach jedem Umschalten (Referenz oder Eingang) die erste Messung verworfen werden muss, weil die Umschalter nicht synchronisiert sind.
Benutzeravatar
xoexlepox
Beiträge: 4815
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von xoexlepox »

Code: Alles auswählen

  temp += 0x80;                // Add 1/2 to get correct rounding on division below 
  temp >>= 8;                  // Divide result to get Kelvin
Ähh, seit wann wird bei einem Integer-Bitshift gerundet? Bei einer Division könnte das vielleicht sogar funktionieren, aber bei einem Shift werden m.E. nur Bits entfernt.
Farbe
Beiträge: 410
Registriert: So 29. Sep 2013, 16:06

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von Farbe »

sukram hat geschrieben: Sa 3. Apr 2021, 23:52 ... die erste Messung verworfen werden muss, ...
Deswegen schalte ih den ADC zwischendurch aus, schalte um, und schalte ihn wieder an.
Die Batterie Messung ergibt auch sinnvoller Ergebnisse beim ersten Messergebnis.
xoexlepox hat geschrieben: So 4. Apr 2021, 07:43 seit wann wird bei einem Integer-Bitshift gerundet?..
Gute frage, eigentlich ja nicht.
Wenn ich das richtig sehe macht das garkeine sinn:
temp ist 32bit (z.b.) = 01110000000000000000000000000001
dann kommt 0x80 hex dazu = 10000000
Temp = 01110000000000000000000010000001
dann wird geschiftet:
Temp = 000000000011100000000000000000000
Also wird es eh komplett raus geschoben??? 0,5 gibt es ja auch garnicht bei einem uint32_t? das stellt doch nur ganze Zahlen da?


Das Stückchen Code kommt aber direkt aus dem Attiny Datenblatt:
It is recommended to follow these steps in user code:

Code: Alles auswählen

int8_t sigrow_offset = SIGROW.TEMPSENSE1; // Read signed value from signature row uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned value from signature row uint16_t adc_reading = 0; // ADC conversion result with 1.1 V internal reference
uint32_t temp = adc_reading - sigrow_offset;
temp *= sigrow_gain; // Result might overflow 16 bit variable (10bit+8bit)
temp += 0x80; // Add 1/2 to get correct rounding on division below temp
 >>= 8; // Divide result to get Kelvin
uint16_t temperature_in_K = temp;
Ich hab mir da keine Gedanken drüber gemacht und das einfach eingefügt. Immerhin weiß ich eh nicht was der Temp sensor genau ausgibt. (und ich habe keine Ahnung von Programmierung)
Benutzeravatar
xoexlepox
Beiträge: 4815
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von xoexlepox »

Das Stückchen Code kommt aber direkt aus dem Attiny Datenblatt
Tja, auch in einem Datenblatt kann Mist stehen ;)
Immerhin weiß ich eh nicht was der Temp sensor genau ausgibt.
Dann schau dir doch mal den A/D-Wert ohne irgendwelche Umrechnung an. Ändert der sich mit der Temperatur? Soweit wie ich es verstanden haben (und wie es in anderen Chips realisiert ist), wird allgemein ein (vom Hersteller einprogrammierter?) "Korrekturwert" von dem A/D-Wert abgezogen, und dann durch eine Konstante geteilt. Von dem Korrekturwert hängt es dann ab, ob du °C oder °K bei dieser Rechnung erhältst.
Farbe
Beiträge: 410
Registriert: So 29. Sep 2013, 16:06

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von Farbe »

Ich hab mal Dablas gewälzt, bei allein ATtinys ist dieser Code Schnipsel drin.
Scheinbar funktioniert das bei anderen auch.

Ich muss mal ein 2. Board bestücken und dort eine Serielle Schnittstelle benutzen. Dann kann ich mir wenigstens die Werte senden.
Aktuell habe ich nur eine LED zur Ausgabe...
Farbe
Beiträge: 410
Registriert: So 29. Sep 2013, 16:06

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von Farbe »

Ich hab heute mal ein 2. Board zusammengelötet und die Serielle Schnittstelle rausgeführt.

ADC sagt immer 1023.. mhm das ist MAX..

Referenz passt..

Dann fällt es mir wie schuppen von den Augen:

Code: Alles auswählen

If(battery == true){
ADC0.MUXPOS = 0b00000111;                                                 // AIN7 as input (connected to vBatt)
}else{
 ADC0.MUXPOS = 0b00000111;                                               // tempsense as input
 }
Ich hab den MUX nicht umgeschalten... scheinbar hab ich die Zeile kopiert und nur das Kommentar geändert. :oops:
mit:

Code: Alles auswählen

ADC0.MUXPOS = 0b00011110;                                               // tempsense as input

gehts auf anhieb.

Was es mit "temp += 0x80; // Add 1/2 to get correct rounding on division below" auf sich hat weiß ich noch nicht. Ohne liefert es die selbe Temperatur raus.
manuel
Beiträge: 769
Registriert: Fr 7. Feb 2014, 00:14

Re: ATtiny1616 internen TEMP Sensor auslesen (Arduino)

Beitrag von manuel »

Das + 127 und dann /256 macht schon Sinn. Die Zahl nach der Multiplikation ist im q8 Format, 0x80 entspricht 0,5.
Antworten