Spannungsüberwachung mit Atmel AVR Prozessoren

Nachdem ich schon vor einiger Zeit etwas mit Spannungsüberwachung gemacht habe, nehme ich das Thema noch einmal neu auf und erweitere die Software für mehrere Atmel AVR Prozessoren, die die interne Spannungsüberwachung unterstützen. Das sind ATMega328, ATMega2560 und ATTiny 25/45/85.
Aus den Datenblättern ergibt sich eine Unterscheidung bei der Initialisierung. Das Auslesen ist bei allen gleich. Die Varianten werden per define als Compilerschalter angelegt.

Headerfile

/****************************************************************************
 * (c) 2019 softwareentwicklung-als-prozess.de
 * Funktionalitaet:
 * Spannungsueberwachung mit dem ADC
 ***************************************************************************/

#ifndef VCTL_HEADER
#define VCTL_HEADER

#define VCTL_VCCOK 5000l
#define VCTL_VCCLOW 4500l

void vctl_Setup(void);
long vctl_Measure(void);

#endif

Cpp Datei

/****************************************************************************
 * (c) 2019 softwareentwicklung-als-prozess.de
 * Funktionalitaet:
 * interne Spannungsueberwachung mit dem ADC
 ***************************************************************************/
#include <arduino.h>
#include "vctl.h"

// verfuegbar fuer folgende Prozessoren - immer nur einen setzen
#define ATMEGA328
//#define ATMEGA2560
//#define ATTINY25_45_85
//#define ANDERE

#ifdef ATMEGA328
void vctl_Setup(void)
{ 
  ADMUX |= (1 << REFS0);                             // VCC als Referenzspannung
  ADMUX |= (1 << MUX3) | (1 << MUX2) | (1 << MUX1);  // VBG als Eingang
  delay(10);                                         // warten bis sich die Referenzspannung eingestellt hat
  ADCSRA |= (1 << ADEN);                             // ADC enable
}
#endif

#ifdef ATMEGA2560
void vctl_Setup(void)
{ 
  ADMUX |= (1 << REFS0);                             // VCC als Referenzspannung
  ADMUX |= (1 << MUX4) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1);  // VBG als Eingang
  delay(10);                                         // warten bis sich die Referenzspannung eingestellt hat
  ADCSRA |= (1 << ADEN);                             // ADC enable
}
#endif

#ifdef ATTINY25_45_85
void vctl_Setup(void)
{ 
  ADMUX = 0;                                         // VCC als Referenzspannung
  ADMUX |= (1 << MUX3) | (1 << MUX2);                // VBG als Eingang
  delay(10);                                         // warten bis sich die Referenzspannung eingestellt hat
  ADCSRA |= (1 << ADEN);                             // ADC enable
}
#endif

#ifdef ANDERE
void vctl_Setup(void)
{ 
// je nach Prozessor - siehe Datenblatt / Datasheet
}
#endif

#if defined(ATMEGA328) || defined(ATMEGA2560) || defined(ATTINY25_45_85)
long vctl_Measure(void)
{
  int adcl, adch;
  long result;
  
  vctl_Setup();                     // fuer jede Messung neu
  ADCSRA |= (1 << ADSC);            // starten
  while (bitRead(ADCSRA, ADSC));    // bis Messung beendet ist
  // Wichtig: zuerst ADCL auslesen, dann ADCH
  adcl = ADCL;
  adch = ADCH & 0x03;               // ADLAR ist standardmaessig auf 0
                                    // also die oberen 6 bit loeschen
  result = (adch << 8) | adcl;
  return(1125300L / result);        // Spannung in millivolt: 1100mV * 1023 = 1125300
}
#endif

#ifdef ANDERE
long vctl_Measure(void)
{
// je nach Prozessor - siehe Datenblatt / Datasheet
  return(0l);
}
#endif

Test
Getestet habe ich mit einem Arduino Uno (ATMega328P) und einem Arduino Mega 2560 (ATMega2560) und einem ATTiny85 auf einem Breadboard explizit aufgebaut. Angeschlossen an ein Labornetzteil, um die Spannung verändern zu können. Der Sketch dazu ist aus „NTC Thermometer mit Korrektur“ entnommen und erweitert mit den obigen Sourcen.

Ergebnis
Die Spannungsmessung hat bei allen funktioniert. Jedenfalls solange man auf dem Display überhaupt noch etwas erkennen konnte… Diesen Wert braucht man auf jeden Fall, wenn man Sensoren einsetzt und deren Messwert in physikalische Einheiten umrechnet.

Links

Spannungsüberwachung
http://physudo.blogspot.de/2014/08/spannung-uberwachen-am-arduino-atmega.html

Spannungsüberwachung und Brown Out Erkennung
http://blog.softwareentwicklung-als-prozess.de/spannungsueberwachung-und-brown-out-erkennung

Verwaltung von Varianten einer Software
http://blog.softwareentwicklung-als-prozess.de/varianten-einer-software-verwalten

NTC Thermometer mit Korrektur
http://blog.softwareentwicklung-als-prozess.de/ntc-thermometer-mit-korrektur

Veröffentlicht von

Jürgen

Ich bin Software Ingenieur und habe meine Schwerpunkte in allen Aktivitäten, die zur Software Entwicklung gehören. Am längsten bin ich als Software Entwickler von Embedded Software in C tätig.