mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Einfache Spannungsmessung attiny15


Autor: NickJag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich finde in meinem quellcode den fehler nicht, und der tiny gibt 
mir einfach an den ausgängen nichts aus, egal welche spannung ich an PB4 
anlege, hab ich etwas vergessen?

An PB4 lege ich eine externe spannung an die gemessen werden soll
an PB0-3 sind einfach leds mit widerstand an gnd angeschlossen

quellcode:
#include <avr/io.h>
#include <inttypes.h>
#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun mit 1000000 definiert"
#define F_CPU 1000000     /* Quarz mit 1 Mhz  */
#endif
#include <util/delay.h>     /* bei alter avr-libc: #include <avr/delay.h> */      



uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADMUX = mux;                      // Kanal waehlen
  
  /* interne Referenzspannung nutzen (atmega8 2.56V) 10-bit = 0-1023
    2.56V/1024 = 0.0025V  4Led's alle 0,5V /0.0025= 200
   200 = 0,5V --> Led1 --> 0b0011001000 --> 0x00C8
   400 = 1,0V --> Led2 --> 0b0110010000 --> 0x0190
   600 = 1,5V --> Led3 --> 0b1001011000 --> 0x0258
   800 = 2,0V --> Led4 --> 0b1100100000 --> 0x0320
  1000 = 2,5V --> Alle --> 0b1111101000 --> 0x03E8
  */
  ADMUX |= (1<<REFS1);
  ADMUX &= ~(1<<REFS0); 


 /* Frequenzvorteiler berechnen 
  TFmin = 1Mhz/200Khz = 5
  TFmax = 1Mhz/50Khz = 20   
  setzen auf 8 (1) und ADC aktivieren (1) */
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    
 
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert
 
  return result;
}
 
 

 
int main()
{

uint16_t LED1 = 0x00C8;
uint16_t LED2 = 0x0190;
uint16_t LED3 = 0x0258;
uint16_t LED4 = 0x0320;
uint16_t ALLE = 0x03E8;


DDRB &= ~(1 << PB4);                          // PB4 als ADC Eingang
DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// PB0-PB3 als Ausgang (LED's)


while(1)
{
  uint16_t wert;
 
  wert = ReadChannel(3); /* MUX-Bits auf 0b0011 -> Channel 3 */

/* Ausgabe der Spannungen an LED's */

  if (wert < LED1)
    {
    PORTB = 0x00;
  }
    if ((wert >= LED1) & (wert < LED2))
  {
    PORTB = (1 << PB0);
  } 
  if ((wert >= LED2) & (wert < LED3))
  {
    PORTB = (1 << PB1);
  }
  if ((wert >= LED3) & (wert < LED4))
  {
    PORTB = (1 << PB2);
  }
  if ((wert >= LED4) & (wert < ALLE))
  {
    PORTB = (1 << PB3);
  }
  if (wert >= ALLE)
  {
    PORTB = (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);
  }

}
 
}


währe nett wenn ihr mir weiterhelfen könntet

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wusste gar nicht, dass man RAMlose AVRs in C programmieren kann...

...

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

zumindest mein WinAVR kann das nicht...

../main.c:1: error: MCU 'attiny15' supported for assembler only

c:/winavr-20090313/lib/gcc/../../avr/include/avr/iotn15.h:51:4: warning: 
#warning "MCU not supported by the C compiler"

Gruß aus Berlin
Michael

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
NickJag wrote:
> An PB4 lege ich eine externe spannung an die gemessen werden soll
> an PB0-3 sind einfach leds mit widerstand an gnd angeschlossen

AVRs haben OC-Ausgänge. Hänge die LED daher zwischen Vcc und Port.

Ansonsten könnte es mit ramlosen AVRs schon funktionieren, wenn die 
Variablen sauber in die Register passen. Kommt aber auf den Compiler 
drauf an. Zur Sicherheit vor den Variablendefinitionen "register" davor 
hängen.
uint16_t ReadChannel(uint8_t mux)
{
  register uint8_t i;
  register uint16_t result;

und
while(1)
{
  register uint16_t wert;


Außerdem:
static uint16_t LED1 = 0x00C8;
static uint16_t LED2 = 0x0190;
...

Hier sollte aber zur Sicherheit überall ein "static" davor stehen. 
Eventuell erkennt es der Compiler aber selber, dass diese Variablen nie 
verändert werden und trägt sie als konstant in den Code ein.

Christian

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian Harf wrote:
> NickJag wrote:
>> An PB4 lege ich eine externe spannung an die gemessen werden soll
>> an PB0-3 sind einfach leds mit widerstand an gnd angeschlossen
>
> AVRs haben OC-Ausgänge. Hänge die LED daher zwischen Vcc und Port.
Unsinn. AVRs haben Push-Pull-Ausgänge und dementsprechend ist es in den 
meisten Fällen wurscht, ob man LEDs High- oder Low-Side anschließt.

> Ansonsten könnte es mit ramlosen AVRs schon funktionieren, wenn die
> Variablen sauber in die Register passen. Kommt aber auf den Compiler
> drauf an. Zur Sicherheit vor den Variablendefinitionen "register" davor
> hängen.
Auch das bringt nichts. Erstens funktioniert es sowieso nur dann, wenn 
der Compiler die besagten Controller überhaupt unterstützt. Und wenn 
er sie unterstützt, dann legt er sich die Variablen schon selber zurecht 
(also da hin, wo Platz ist)!

Der Typqualifizierer register bringt hier nicht nur nichts, der 
Compiler ist auch generell nicht daran gebunden. Und ein Compiler, der 
die RAM-losen AVRs unterstützt, weiß selber, dass er Variablen in 
Register legen muss. Wohin auch sonst?

> Hier sollte aber zur Sicherheit überall ein "static" davor stehen.
> Eventuell erkennt es der Compiler aber selber, dass diese Variablen nie
> verändert werden und trägt sie als konstant in den Code ein.
Hä? Bitte nimm Dir ein gutes C-Buch zur Hand und lies es gründlich 
durch! static hat ausschließlich einen Einfluss auf den 
Gültigkeitsbereich (Scope) einer Variablen. Es hat weder etwas mit 
"konstant" noch mit dem "Verändern" von Variablen zu tun! Außerdem trägt 
der Compiler nirgends etwas als "konstant" ein.

Bei wenig Speicherressourcen sollte man auf lokale /static/-Variablen 
eher verzichten, weil die genau wie globale Variablen permanent den 
ihnen zugeteilten Speicher belegen!

Eine Variable, die sich nicht verändert, gehört übrigens in den 
Flash-Speicher und nicht ins RAM und erst recht nicht in ein Register...

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zum einen:
> /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
>     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" >*/
das ist nur 1x nach Reset notwendig

und zum anderen was zumindest ein wichtiger Fehler ist:
>    if ((wert >= LED1) & (wert < LED2))
du meintest vermutlich && statt &

Autor: Felix F. (wiesel8)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
hab auch mal ne Spannungsanzeige auf nen atmega8 gemacht. Weil es aber 
mehr als 5V waren, hab ich einfach 3x10k widerstände in reihe geschaltet 
und von einem die Spannung abgenommen.

(in basic)

dim A(und B) as Single

A = 5 / 1024   // für 5V und 10-bit

B = (ADC-Wert * A) * 3    // * 3 wegen spannungsteiler

und dann mit Fusing b so umwandeln dass es ausgegeben werden kann (vlt. 
gehts in C auch so)

mfg

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter wrote:
> zum einen:
>> /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
>>     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" >*/
> das ist nur 1x nach Reset notwendig
Nein, das ist nach dem Aktivieren des ADC über ADEN notwendig. Und wenn 
man den ADC nach jeder Wandlung ausschaltet, sollte man auch bei jedem 
Wiedereinschalten einen Dummy-Read-Out machen. Allerdings ist es in den 
meisten Fällen sinnvoll, den ADC einfach anzulassen. Nur wenn man 
wirklich Strom sparen muss und nur sporadisch wandelt, sollte man den 
ADC nach einer Messung ausschalten.

> und zum anderen was zumindest ein wichtiger Fehler ist:
>>    if ((wert >= LED1) & (wert < LED2))
> du meintest vermutlich && statt &
Ist in dem Fall aber egal. Beide Teilausdrücke können nur 0 oder 1 sein, 
und da klappt es auch mit nem bitweisen UND.

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Unsinn. AVRs haben Push-Pull-Ausgänge und dementsprechend ist es in den
> meisten Fällen wurscht, ob man LEDs High- oder Low-Side anschließt.
Hmm, stimmt. Habe gerade nochmal in der Doku nachgeschaut. Sorry, dann 
war ich bisher immer falsch informiert. Ich meinte, mal sowas gelesen zu 
haben.
Danke für den Hinweis.

> Der Typqualifizierer register bringt hier nicht nur nichts, der
> Compiler ist auch generell nicht daran gebunden. Und ein Compiler, der
> die RAM-losen AVRs unterstützt, weiß selber, dass er Variablen in
> Register legen muss. Wohin auch sonst?

Kommt auf den Compiler an. Wenn er nichts davon weiß, ob Ram oder kein 
Ram, dann ist "register" notwendig. Ich weiß natürlich nicht, was hier 
für ein Compiler verwendet wird.

"Normally, the compiler determines what data is to be stored in the 
registers of the CPU at what times. However, the C language provides the 
storage class register so that the programmer can ``suggest'' to the 
compiler that particular automatic variables should be allocated to CPU 
registers, if possible. Thus, register variables provide a certain 
control over efficiency of program execution. Variables which are used 
repeatedly or whose access times are critical, may be declared to be of 
storage class register."

> Hä? Bitte nimm Dir ein gutes C-Buch zur Hand und lies es gründlich
> durch! static hat ausschließlich einen Einfluss auf den
> Gültigkeitsbereich (Scope) einer Variablen. Es hat weder etwas mit
> "konstant" noch mit dem "Verändern" von Variablen zu tun! Außerdem trägt
> der Compiler nirgends etwas als "konstant" ein.
Sorry, habe schon zielich lange nicht mehr in C programmiert. Hatte C&R 
das auch schon so gesehen? Ich muß bei Zeiten meine C-Kenntnisse nochmal 
auffrischen.

Jaja, mann sollte keine Java-Konstrukte in C zurückführen und dann noch 
die Hälfte ("final") vergessen. Ich nehme alles zurück und behaupte das 
Gegenteil.

> Bei wenig Speicherressourcen sollte man auf lokale /static/-Variablen
> eher verzichten, weil die genau wie globale Variablen permanent den
> ihnen zugeteilten Speicher belegen!
Meist optimiert der Compiler nur einmalig benutzte und nicht veänderte 
Variablen sowieso weg.

Was ich eigentlich meinte, war ein "#define". Also statt "uint16_t LED1 
= 0x00C8;" schreibt man besser "#define LED1 0x00C8". Das ist dann aber 
nichts für den C-Compiler, sondern für den Präprozessor.

> Eine Variable, die sich nicht verändert, gehört übrigens in den
> Flash-Speicher und nicht ins RAM und erst recht nicht in ein Register...
Das habe ich auch nie gesagt. Ich wollte nur, dass der Compiler die 
konstanten "Variablen" wegoptimiert. Ins Register gehören natürlich alle 
kurzlebigen Variablen. Wenn diese knapp werden, muss man halt ins RAM 
auslagern (wenn vorhanden).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.