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


von Jonas A. (jonas2098)


Angehängte Dateien:

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.

von Wolfgang (Gast)


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.

von Jonas A. (jonas2098)


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.

von Wolfgang (Gast)


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.

von Michael B. (laberkopp)


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
1
char ziffer[5]; //eins mehr wegen NUL Terminator
und die Umsetzung in 7-Segment Muster
1
byte segment[10] = {0xC0,0xF9,0xA4,0xAA,0xA2,0x92,0x82,0xF8,0x80,0x90};
macht
1
byte digit=0;
2
void loop()
3
{
4
  if(digit>3) digit=0;
5
  PORTD=0;
6
  PORTB=1<<digit;
7
  PORTD=segment[ziffer[digit]];
8
  digit++;
9
  delay(10); // eine kurze Zeit Ziffer stehen lassen
10
}

die Anzeige.

Dein delay(250) muss dann eben bei jedem 25. Durchlauf von loop 
passieren
1
byte pass=0;
2
void loop()
3
{
4
  if(digit>3) digit=0;
5
  PORTD=0;
6
  PORTB=1<<digit;
7
  PORTD=segment[ziffer[digit]];
8
  digit++;
9
  pass++
10
  if(pass>=25)
11
  {
12
    lmVal = analogRead(lmPin);
13
    tem = (lmVal * 0.002852467311 * 100);//5/1024=0.0048828125;1000/10=100
14
    sprintf(ziffer,"%04d",tem);
15
    pass=0;
16
  }
17
  delay(10);
18
}
Ein anderer schriebt
https://www.jameco.com/Jameco/workshop/TechTip/working-with-seven-segment-displays.html

: Bearbeitet durch User
von Peter D. (peda)


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.

von Maxim B. (max182)


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!

von Wolfgang (Gast)


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.

von Manfred (Gast)


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.

von Maxim B. (max182)


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.

von Manfred (Gast)


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.

von Georg M. (g_m)


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

von Maxim B. (max182)


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
von Stefan F. (Gast)


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.

von Maxim B. (max182)


Angehängte Dateien:

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:
1
void sekdec(int a){ /* Die Funktion wandelt a in Bereich 0-5999 
2
nach BCD und speichert das in Puffer zif_ind.
3
Wird verwendet, um a zu indizieren */
4
  for(int i=0;i<4;i++){
5
      zif_ind[i] = 0;
6
        }
7
  while(a>=600)
8
    {
9
      zif_ind[0]++;
10
      a-=600;
11
    }
12
  while(a>=60)
13
    {
14
      zif_ind[1]++;
15
      a-=60;
16
    }
17
  while(a>=10)
18
    {
19
      zif_ind[2]++;
20
      a-=10;
21
    }
22
  while(a>=1)
23
    {
24
      zif_ind[3]++;
25
      a-=1;
26
    } 
27
  // Null loeschen
28
    if (zif_ind[0] == 0) zif_ind[0] = ZIF_LEER_CODE;
29
}

 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:
1
/* Hier ist LED-Indikator beschrieben */
2
#define RASR_MAX 4  /* Zahl der Ziffer */
3
#define PRASR PORTC /* Port fuer gemeinsame Kathoden */
4
#define DDR_RASR DDRC
5
6
#define RAS0 PC5  /* Ziffer 1 (links) */
7
#define RAS1 PC4  /* Ziffer 2 */
8
#define RAS2 PC3  /* Ziffer 3 */
9
#define RAS3 PC2  /* Ziffer 4 (rechts) */
10
11
#define RASR_0 (1<<RAS0)
12
#define RASR_1 (1<<RAS1)
13
#define RASR_2 (1<<RAS2)
14
#define RASR_3 (1<<RAS3)
15
#define RAS_AUS (PRASR |= RASR_0|RASR_1|RASR_2|RASR_3) /* alle ausschalten */
16
17
#define PSEG PORTD /* Port fuer Segmenten-Anoden */
18
#define DDR_SEG DDRD
19
20
#define SEG_A PD7
21
#define SEG_B PD0
22
#define SEG_C PD2
23
#define SEG_D PD4
24
#define SEG_E PD5
25
#define SEG_F PD6
26
#define SEG_G PD1
27
#define SEG_H PD3
28
29
#define ZIF_0 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
30
#define ZIF_1 (1<<SEG_B)|(1<<SEG_C)
31
#define ZIF_2 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
32
#define ZIF_3 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_G)
33
#define ZIF_4 (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_F)|(1<<SEG_G)
34
#define ZIF_5 (1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)
35
#define ZIF_6 (1<<SEG_A)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
36
#define ZIF_7 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)
37
#define ZIF_8 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
38
#define ZIF_9 (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_F)|(1<<SEG_G)
39
#define ZIF_a (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
40
#define ZIF_b (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
41
#define ZIF_c (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
42
#define ZIF_d (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
43
#define ZIF_e (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
44
#define ZIF_f (1<<SEG_A)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
45
/* 0x10 "-" */
46
#define ZIF_MINUS (1<<SEG_G)
47
/* 0x11 */
48
#define ZIF_P (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
49
/* 0x12 */
50
#define ZIF_PUM (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_F)|(1<<SEG_G)
51
/* 0x13 */
52
#define ZIF_PR (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
53
/* 0x14 */
54
#define ZIF_PRK (1<<SEG_C)|(1<<SEG_E)|(1<<SEG_G)
55
/* 0x15 */
56
#define ZIF_h (1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
57
/* 0x16 */
58
#define ZIF_H (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
59
/* 0x17 */
60
#define ZIF_KLAML (1<<SEG_A)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
61
/* 0x18 */
62
#define ZIF_KLAMR (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)
63
/* 0x19 */
64
#define ZIF_KLL_KL (1<<SEG_D)|(1<<SEG_E)|(1<<SEG_G)
65
/* 0x1a */
66
#define ZIF_KLR_KL (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_G)
67
/* 0x1b */
68
#define ZIF_TL (1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)
69
/* 0x1c */
70
#define ZIF_TR (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_G)
71
/* 0x1d "U" */
72
#define ZIF_U (1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)
73
/* 0x1e "u" */
74
#define ZIF_UK (1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)
75
/* 0x1f */
76
#define ZIF_LEER 0
und so:
1
static const char semiseg[16] PROGMEM = {ZIF_0,ZIF_1,ZIF_2,ZIF_3,
2
ZIF_4,ZIF_5,ZIF_6,ZIF_7,ZIF_8,ZIF_9,
3
ZIF_MINUS,ZIF_LEER,ZIF_LEER,ZIF_LEER,ZIF_LEER,ZIF_LEER};
4
5
#define ZIF_LEER_CODE 15
6
7
static const char semiras[4] PROGMEM = {RASR_0,RASR_1,RASR_2,RASR_3};
8
9
static unsigned char rasr = 0;
10
char zif_ind[4] = {0,0,0,0};
11
12
void ind(void){ /* wird fuer Regenerieren abgerufen */
13
  unsigned char x;
14
  RAS_AUS;
15
  rasr++;
16
  if(rasr == RASR_MAX) rasr = 0;
17
  x = zif_ind[rasr];
18
  PSEG = pgm_read_byte (&semiseg[x]);
19
20
  /* Doppelpunkt blinkt nur wenn Sekunden gezaehlt */
21
22
  if(!(FLAGG & (1<<EF_SEK))) PSEG |= (1<<SEG_H);
23
    else if((FLAGG & (1<<F_DP))) PSEG |= (1<<SEG_H);
24
        else PSEG &= ~(1<<SEG_H);
25
26
  x = pgm_read_byte (&semiras[rasr]);
27
  PRASR &= ~x;
28
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.