mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Arduino Uno Temperatur auf 4 stelligen 7 Segmentanzeige


Autor: Jonas A. (jonas2098)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo , ich wollte einen Temperaturwert von einem LM 35 Temperatursensor 
mit Hilfe eines Arduino Unos auf vier 7 Segmentanzeigen mit 4 Ziffern 
den Temperaturwert anzeigen lassen. Leider habe ich keine Idee wie der 
Programmcode aussehen soll. Ich habe nur einen Programmcode der mir den 
Wert auf dem Serial Monitor anzeigt.

Hier der Code der mir das auf dem Serial Monitor anzeigt:
(der Code ist nicht von mir  entwickelt  worden ... ich hab ihn nur 
verändert)
//LM35 output voltage has a linear relation with the Celsius 
temperature, output of 0 v when 0 ℃,
//every increase 1 ℃, the output voltage increase 10 mv
#define lmPin A0  //LM35 attach to


float tem = 0;
long lmVal = 0;

void setup()

 {

  Serial.begin(9600); //initialize serial monitor



}
void loop()
{

  lmVal = analogRead(lmPin);
  tem = (lmVal * 0.002852467311 * 100);//5/1024=0.0048828125;1000/10=100
  Serial.print("//////");

  Serial.print(tem);

  delay(250);


}


- Diesen Wert der im Serial Monitor angezeigt wird soll auf einer 4 
Stelligem 7 Segmentanzeige angezeigt werden .  ( im Bild ist leider 
nicht der Temperatursensor zu sehen aber so soll das 4rer 7 Segment 
Display angeschlossen werden.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jonas A. schrieb:
> Leider habe ich keine Idee wie der
> Programmcode aussehen soll. Ich habe nur einen Programmcode der mir den
> Wert auf dem Serial Monitor anzeigt.
>
Damit kannst du keine Werte auf der 7-Segment Anzeige ausgeben.

> Hier der Code der mir das auf dem Serial Monitor anzeigt:
> (der Code ist nicht von mir  entwickelt  worden ... ich hab ihn nur
> verändert)

Dann wirst du ihn weiter verändern müssen.

Wenn du ihn nicht selbst schreiben möchtest, musst du vielleicht Tante 
Google fragen. Außerdem muss dein Schaltplan, die Anzeigen und das 
Programm zusammenpassen. Ohne darüber etwas zu wissen, ist es mit 
konkreten Tips schlecht.

Außerdem überschätzt du anscheinend die Genauigkeit deines Sensors. 
Jedenfalls brauchen die Konstanten in der Rechnung nicht mehr Stellen zu 
besitzen, als dein µC verarbeiten kann und als es der Genauigkeit des 
Endergebnisses nützt. Das schwächste Glied in der Verarbeitungskette 
dürfte der Sensor sein.

Autor: Jonas A. (jonas2098)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Ja ich weiß , dass der Temperatursensor eh nur auf 0,5 Grad genau ist 
... und das vier Stellen da auch nichts bringen ... . Hab aber nur eine 
Anzeige mit vier Stellen und eine mit einer Stelle ... also muss ich die 
vierer nehmen und ja ich weiß dass ich mit Google suchen kann und das 
hab ich auch nur leider hab ich nichts gefunden dass genau zu meinem 
Projekt passt ... ich dachte nur das jemand da vllt mehr weiß wie ich 
das programmieren kann. Und ja der Code den in da hab das sollen auch 
nur die Rohdaten sein ... wenn ich wüsste wie ich das machen müsste 
würde ich nicht fragen ... und natürlich hab ich mir schon etliche 
Seiten dazu durchgeguckt.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jonas A. schrieb:
> Hab aber nur eine Anzeige mit vier Stellen und eine mit einer Stelle

Ok

> ... ich dachte nur das jemand da vllt mehr weiß wie ich das
> programmieren kann.

Dafür müsste man erstmal mehr über deine Anzeigen wissen, als du bisher 
verraten hast. Oft ist Multiplexbetrieb eine Lösung.

Autor: Michael B. (laberkopp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jonas A. schrieb:
> - Diesen Wert der im Serial Monitor angezeigt wird soll auf einer 4
> Stelligem 7 Segmentanzeige angezeigt werden

Nun, ich sehe nicht genau welche Anzeigen (common cathode oder common 
andode) und welche Segmentew an welche Anschlüsse gehe, aber wenn dir 
die 5mA Segmentstrom ausreichen die diese Schaltung maximal schafft, ist 
die Ansteuerung doch klar, angenommen die Segmente abcdefg liegen an 
PORTD, die Digits an PORTB.0...3 wären gemeinsame Anode:

In loop musst je jedesmal eine Ziffer aktivieren. Stehen die ziffern in
char ziffer[5]; //eins mehr wegen NUL Terminator
und die Umsetzung in 7-Segment Muster
byte segment[10] = {0xC0,0xF9,0xA4,0xAA,0xA2,0x92,0x82,0xF8,0x80,0x90};
macht
byte digit=0;
void loop()
{
  if(digit>3) digit=0;
  PORTD=0;
  PORTB=1<<digit;
  PORTD=segment[ziffer[digit]];
  digit++;
  delay(10); // eine kurze Zeit Ziffer stehen lassen
}

die Anzeige.

Dein delay(250) muss dann eben bei jedem 25. Durchlauf von loop 
passieren
byte pass=0;
void loop()
{
  if(digit>3) digit=0;
  PORTD=0;
  PORTB=1<<digit;
  PORTD=segment[ziffer[digit]];
  digit++;
  pass++
  if(pass>=25)
  {
    lmVal = analogRead(lmPin);
    tem = (lmVal * 0.002852467311 * 100);//5/1024=0.0048828125;1000/10=100
    sprintf(ziffer,"%04d",tem);
    pass=0;
  }
  delay(10);
}
Ein anderer schriebt
https://www.jameco.com/Jameco/workshop/TechTip/wor...

: Bearbeitet durch User
Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Such mal nach "Multiplexanzeige c", da wirst Du tonnenweise Code finden.
Allerdings sind die Portpins nicht in der Lage ein Digit zu treiben, 
d.h. Du brauchst je Digit noch einen Transistor.

Autor: Maxim B. (max182)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jonas A. schrieb:
> aber so soll das 4rer 7 Segment
> Display angeschlossen werden.

Wenn das schon sowieso Arduino ist (d.h. keine freie ISR von Timer 
verfügbar), wäre es vielleicht besser, eine Anzeige mit Max7219 zu 
benutzen? Bei Chinesen kostet 8-Ziffer-Anzeige unter 2 €. MOSI, CLK, 
~WR, einmal 4 Ziffer geschrieben - und vergessen!

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim B. schrieb:
> Wenn das schon sowieso Arduino ist (d.h. keine freie ISR von Timer
> verfügbar)

Wieso ist beim Arduino keine Timer ISR verfügbar?
Der Arduino 1ms-Interrupt nutzt nur den Timer0 und alles weitere hängt 
von der Anwendung ab.

Autor: Manfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim B. schrieb:
> Wenn das schon sowieso Arduino ist (d.h. keine freie ISR von Timer
> verfügbar), wäre es vielleicht besser, eine Anzeige mit Max7219 zu
> benutzen?

Quark! Das einzige Problem ist Jonas' Unfähigkleit, sein "Problem" in 
zwei Teile zu zerlegen und logisch abzuarbeiten - Arduino-Klischee 
wieder bedient, schade. Wenn man es nicht selber kann, finden sich im 
Internet ganz sicher fertige Libraries zur Ansteuerung einer 
Siebensegmenteinheit. Diese dann mit der, ebenfalls kopierten, 
Sensorabfrage zu verheiraten, sollte das große Problem nicht sein.

Wenn das Ding nichts weiter zu tun hat, als einen LM35 auf das Display 
zu bringen, bekommt man das sogar noch mit delay() in der loop() hin.

Wer gerne möchte und lesen kann, findet auch beim Arduino einen 
Timer-Interrupt.

Autor: Maxim B. (max182)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manfred schrieb:
> finden sich im
> Internet ganz sicher fertige Libraries zur Ansteuerung einer
> Siebensegmenteinheit

Das finde ich eigentlich schlecht. Man verwendet etwas, was man nicht 
gut versteht. Und Arduino-IDE hilft wenig, Quelltext zu verstehen.

Autor: Manfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim B. schrieb:
> Manfred schrieb:
>> finden sich im Internet ganz sicher fertige Libraries zur Ansteuerung einer
>> Siebensegmenteinheit
> Das finde ich eigentlich schlecht. Man verwendet etwas, was man nicht gut 
versteht.

Da will ich Dir nicht widersprechen! Genau das ist aber das Konzept 
diverser Hochsprachen, sich nicht um jeden Standardkram selbst kümmern 
zu wollen. Man linkt vorgefertigte Methoden rein und erwartet, dass die 
das tun, was in deren Doku steht.

Das darfst Du unabhängig von Arduino betrachten: Wer schreibt in Delphi 
seine eigene V.24-Routine, wer in Java eine eigene Debugausgabe und 
weitere. Ich sehe keinen Anlass, mich um mein LC-Display oder die 
Abfrage eines I2C-Sensors zu kümmern, da gibt es fertige Dinge. Ich 
schreibe meine Kernaufgaben selbst, die peripheren Dinge gucke ich nur 
an, wenn sie irgendwie nicht tun, was ich brauche.

> Und Arduino-IDE hilft wenig, Quelltext zu verstehen.

Die A*-IDE ist Editor und Compilersteuerung, das Verständnis der Sprache 
muß man sich unabhängig von dieser erarbeiten.

Was ich seit Jahren immer wieder herunterbete: Grundlagen! Abfrage eines 
Schalters, ein Lauflicht, ein Drehpoti abfragen, Hello World aufs 
Display schreiben ... und erst, wenn das zuverlässig klappt, komplexere 
Dinge angehen. Wer dazu nicht bereit ist, sollte sich ein anderes Hobby 
suchen.

Autor: Georg M. (g_m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manfred schrieb:
> Wenn man es nicht selber kann, finden sich im
> Internet ganz sicher fertige Libraries zur Ansteuerung einer
> Siebensegmenteinheit.

https://github.com/DeanIsMe/SevSeg

Autor: Maxim B. (max182)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manfred schrieb:
> Wer schreibt in Delphi
> seine eigene V.24-Routine, wer in Java eine eigene Debugausgabe und
> weitere.

Das sind verschiedene, unvergleichbare Gebiete: ein Computer, wo 
Grundaufbau geregelt ist, und Mikrocontroller, wo man frei bleibt.

: Bearbeitet durch User
Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Bevor man eine 7-Segment Matrixanzeige programmiert, sollte man erst mit 
einer einstelligen Anzeige beginnen. Und dann man über deren 
Stromaufnahme nachdenken, bevor man es vervierfacht.

Autor: Maxim B. (max182)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Moderne LED brauchen nicht viel.
Bei mir arbeitet das in einem Timer ganz gut. (5V - 2V(LED)- 0,9V 
(Transistor + IC)) / 330 ~= 6,4 mA, oder in Durchschnitt 6,4/4=1,6 mA, 
und das ist schon genug hell. Man kann aber 3x oder 4x mehr holen.

Aber ich habe auf C programmiert, deshalb paßt mein Code für TO leider 
nicht: er will ja Arduino benutzen.

Ansonsten nichts kompliziertes: man speichert irgendwie Wert, den man 
zeigen will. Danach in BCD (entweder wie oft mit / und %, oder für AVR 
viel schneller mit Decrement und Vergleich). Z.B. so:
void sekdec(int a){ /* Die Funktion wandelt a in Bereich 0-5999 
nach BCD und speichert das in Puffer zif_ind.
Wird verwendet, um a zu indizieren */
  for(int i=0;i<4;i++){
      zif_ind[i] = 0;
        }
  while(a>=600)
    {
      zif_ind[0]++;
      a-=600;
    }
  while(a>=60)
    {
      zif_ind[1]++;
      a-=60;
    }
  while(a>=10)
    {
      zif_ind[2]++;
      a-=10;
    }
  while(a>=1)
    {
      zif_ind[3]++;
      a-=1;
    } 
  // Null loeschen
    if (zif_ind[0] == 0) zif_ind[0] = ZIF_LEER_CODE;
}

 Dann in ISR jede ein paar ms nimmt man Ziffer nacheinander, wandelt sie 
in 7-segm. Code (dabei kann man es so einrichten, wie das für die Platte 
bequemer ist. Für AVR ist das ja egal, welche Pin zu welchem Segment 
kommt). Dann noch eine (von vier) Kathode auf Null setzen...
Z.B. so:
/* Hier ist LED-Indikator beschrieben */
#define RASR_MAX 4  /* Zahl der Ziffer */
#define PRASR PORTC /* Port fuer gemeinsame Kathoden */
#define DDR_RASR DDRC

#define RAS0 PC5  /* Ziffer 1 (links) */
#define RAS1 PC4  /* Ziffer 2 */
#define RAS2 PC3  /* Ziffer 3 */
#define RAS3 PC2  /* Ziffer 4 (rechts) */

#define RASR_0 (1<<RAS0)
#define RASR_1 (1<<RAS1)
#define RASR_2 (1<<RAS2)
#define RASR_3 (1<<RAS3)
#define RAS_AUS (PRASR |= RASR_0|RASR_1|RASR_2|RASR_3) /* alle ausschalten */

#define PSEG PORTD /* Port fuer Segmenten-Anoden */
#define DDR_SEG DDRD

#define SEG_A PD7
#define SEG_B PD0
#define SEG_C PD2
#define SEG_D PD4
#define SEG_E PD5
#define SEG_F PD6
#define SEG_G PD1
#define SEG_H PD3

#define ZIF_0 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
#define ZIF_1 (1<<SEG_B)|(1<<SEG_C)
#define ZIF_2 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
#define ZIF_3 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_G)
#define ZIF_4 (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_5 (1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_6 (1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_7 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)
#define ZIF_8 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_9 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_a (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_b (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_c (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
#define ZIF_d (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
#define ZIF_e (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
#define ZIF_f (1<<SEG_A)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x10 "-" */
#define ZIF_MINUS (1<<SEG_G)
/* 0x11 */
#define ZIF_P (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x12 */
#define ZIF_PUM (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_F)|(1<<SEG_G)
/* 0x13 */
#define ZIF_PR (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x14 */
#define ZIF_PRK (1<<SEG_C)|(1<<SEG_E)|(1<<SEG_G)
/* 0x15 */
#define ZIF_h (1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x16 */
#define ZIF_H (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x17 */
#define ZIF_KLAML (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
/* 0x18 */
#define ZIF_KLAMR (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)
/* 0x19 */
#define ZIF_KLL_KL (1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
/* 0x1a */
#define ZIF_KLR_KL (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_G)
/* 0x1b */
#define ZIF_TL (1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
/* 0x1c */
#define ZIF_TR (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_G)
/* 0x1d "U" */
#define ZIF_U (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
/* 0x1e "u" */
#define ZIF_UK (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)
/* 0x1f */
#define ZIF_LEER 0

und so:
static const char semiseg[16] PROGMEM = {ZIF_0,ZIF_1,ZIF_2,ZIF_3,
ZIF_4,ZIF_5,ZIF_6,ZIF_7,ZIF_8,ZIF_9,
ZIF_MINUS,ZIF_LEER,ZIF_LEER,ZIF_LEER,ZIF_LEER,ZIF_LEER};

#define ZIF_LEER_CODE 15

static const char semiras[4] PROGMEM = {RASR_0,RASR_1,RASR_2,RASR_3};

static unsigned char rasr = 0;
char zif_ind[4] = {0,0,0,0};

void ind(void){ /* wird fuer Regenerieren abgerufen */
  unsigned char x;
  RAS_AUS;
  rasr++;
  if(rasr == RASR_MAX) rasr = 0;
  x = zif_ind[rasr];
  PSEG = pgm_read_byte (&semiseg[x]);

  /* Doppelpunkt blinkt nur wenn Sekunden gezaehlt */

  if(!(FLAGG & (1<<EF_SEK))) PSEG |= (1<<SEG_H);
    else if((FLAGG & (1<<F_DP))) PSEG |= (1<<SEG_H);
        else PSEG &= ~(1<<SEG_H);

  x = pgm_read_byte (&semiras[rasr]);
  PRASR &= ~x;
}

: Bearbeitet durch User

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.