Kommazahl auf LCD

Hallo,

habe ein kleines Problem. und zwar möchte ich einen Analogwert mit "," auf dem LCD

Long ACD1 = 0; //Analogwert Long Wert1 = 0; // Mapwert Long vkomma ; //vorkomma stellen Long nkomme; // nachkomma stellen

Wert1 = map(ADC1, 205, 1023 , 10000, 1000000); //Durchflusswert 1-5V 10-1000 Liter größer gewählt, sa sonst kommastellen fehlen

wenn ich nun den long wert 22.042 habe wird daraus

vkomma : 22 nkomma: 42 also: 22,42

wie bekomme ich vor der 42 eine 0 gesetzt? reichen würde mich 2 stellen nach dem komma also 22,04 habt ihr da eine idee?

auch und noch was, habe mir die Mapformel in Excel eingebaut aber die werte Stimmen nicht mit dem des Arduinos überein :( (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; =(1023-205)*(1000-10)/(1023-205)+10

oder habe ich in der formel ein verständnissfehler?

vielen Dank

Sketch wäre hilfreich!

wenn ich nun den long wert 22.042 habe wird daraus

vkomma : 22
nkomma: 42
also: 22,42

Das liegt daran, dass du die führende Null nicht ausgibst.

Baue dir eine einfache Hilfsfunktion zur Ausgabe.

void print2digits(int nkomma) {
if(nkomma < 10) lcd.print("00");
else if(nkomma < 100) lcd.print("0");
lcd.print(nkomma);
}

schau Dir mal printf bzw. sprintf und die Formatstrings dazu an.

Zuerst zur Excel-Formel:

Excel rechnet immer mit float, der Arduino mit int (bzw long int).
Du mußt also in Excel Quotienten immer mit GANZZAHL() in int verwandeln.
Dummerweise ist in der MAP-Formel die Reihenfolge nicht festgelegt, wenns ganz blöd läuft, rechnet der Arduino das so:
=(1023-205)*GANZZAHL((1000-10)/(1023-205))+10

Zu deiner Ausgabe:
ich hätte da eine Funktion, die das macht:

/*************************************************************************************************
**  Funktion Write2LCDi									**
**************************************************************************************************
** Funktion zum schreiben eines Wertes Long int-WERTES rechtsbündig in das spezifierte Feld	**
**  											   	**
**  Input: 											**
**  	Val: der zu schreibende Wert.								**
**  	FeldLaenge: Länge des zu bedruckenden Feldes						**
**  	Zeile, Spalte: Erstes Zeichen des zu beschreibenden Feldes				**										**
**  Output: false wenn Wert zu groß für Feld ist, sonst true					**
**  genutzte Globale Variablen:  keine								**
**************************************************************************************************/

boolean Write2LCDi(long int Val, byte FeldLaenge, byte Zeile, byte Spalte){
    
  // bestimmen der Länge der Zahl 
  int SVK;
  if      (abs(Val) >= 100000) SVK = 6;
  else if (abs(Val) >=  10000) SVK = 5;
  else if (abs(Val) >=   1000) SVK = 4;
  else if (abs(Val) >=    100) SVK = 3;
  else if (abs(Val) >=     10) SVK = 2;
  else                         SVK = 1;
  if (Val < 0) SVK++;  // Ein Platz mehr fürs Minuszeichen

  lcd.setCursor(Spalte, Zeile);
  // Wertebereich prüfen: Überprüfung ob Wert ins Feld paßt
  if (SVK > FeldLaenge){                                   //  bei Bereichsüberschreitung
    for (int i = 0; i < FeldLaenge; i++) lcd.print("H");       // Ausgabe "HHH"
    return false;
  } 
  
  // Ausgabe des formatierten Wertes
  for (SVK; SVK < FeldLaenge; SVK++) lcd.print(" ");  // führende Leestellen ausgeben.
  lcd.print(Val);  

} // End Write2LCDi

Für deine Zwecke müsstest du in der Zeile

  for (SVK; SVK < FeldLaenge; SVK++) lcd.print(" ");  // führende Leestellen ausgeben.

nur die “lcd.print(” "); " gegen "lcd.print(“0”); " ändern.

oder du gibst das ganze als float aus, mit der angehängten Funktion Write2LCDf()
Write2LCDf(Wert1/1000.0, 7, 3 , Zeile, Spalte);

write2LCDf.ino (2.29 KB)

Oha, da hat sich der Gunther aber Mühe gegeben mit seiner Formel. So umfangreich hatte ich die dann doch nicht :open_mouth:

sschultewolter: Oha, da hat sich der Gunther aber Mühe gegeben mit seiner Formel. So umfangreich hatte ich die dann doch nicht :open_mouth:

Das hat sich so ergeben. Ich hatte ein Projekt, bei dem ich in vielen Menues unterschiedliche Werte ausgeben mußte. zuerst habe ich bei jeder Ausgabe die Ausgabe einzeln formtiert, dann Funktionen für verschiedene Feldlängen erstellt, und irgendwann ist mir das zu blöd geworden und ich habe für int und float jeweils eine Funktion geschrieben, die alles kann. (und selbst die beiden könnte man noch zusammenfassen, aber das Projekt ist längst fertig)

hat super geklappt :)

vielen Dank.

gibt es einge seite um das gut zu lernen?

könnte man in der IDE auch richtig programmieren also in C ?

könnte man in der IDE auch richtig programmieren also in C ?

Ja. Du musst nur Funktionen vor der Verwendung deklarieren, dann ist es richtiges c++.

void setup()
{
    mysetup();  // in "richtigem c" so nicht erlaubt
}

void mysetup()  // zu spät definiert
{
}

In “richtigem C” musst du die Reihenfolge der Funktionen tauschen, oder vor setup wenigstens eine Deklaraktion
stehen haben.

include <Arduino.h>
void mysetup();

Diese 2 Zeilen fügt die IDE am Anfang ein, dann ist es richtiges C.
Das kannst du, wenn du willst, auch selbst machen.

okay,

kennst du evtl gute lernseiten?

wie sähe denn das Blink in richtigem C dann aus?
so oder durch die ide dann doch wieder anders?

int main (void) {            
  DDRB  = 0xff;             
  while(1) {                
    PORTB |= (1<<PB1);    //Bit setzen
    _delay_ms(500);       // halbe sekunde warten
    PORTB &= ~(1<<PB1);   // Bit loeschen
    _delay_ms(500);       // halbe sekunde warten
  }                         
 return 0;                 
}

Wenn du wirklich kein Problem mit den rein-C Bitfricklereien hast, wäre es vielleicht ne Idee, gleich die richtige AVR-IDE (AVR Studio) zu probieren.

Für Non-Windows Systeme gibt es AVRDUDE und AVR-GCC einfach zu bekommen... Arduino hat manchmal bei nativer C Programmierung nen paar uncoole Quirks, gerade was z.B. das Power Managment oder die Interrupts angeht.

Viele Grüße, Tobias

Das kannst du, wenn du willst, auch in der Arduino IDE machen.
Da gibt es die Funktion main natürlich schon, dein Beispiel heisst also

#include <util/delay.h>
void setup()    {   DDRB  = 0xff; }
void loop()
{
    PORTB |= (1<<B1);    //Bit setzen
    _delay_ms(500);       // halbe sekunde warten
    PORTB &= ~(1<<B1);   // Bit loeschen
    _delay_ms(500);       // halbe sekunde warten
}

edit : so übersetzt es zumindest

Falls auf deiner Hardware Pin 13 (der mit der LED ) PortB Bit 1 sein sollte.
( Das nimmt dir die IDE übrigens auch ab )

Schneller läuft der sketch hoffentlich nicht, ob sich der geringere Speicherbedarf lohnt*), ist die Frage.

Aber warum in der IDE programmieren, wenn du dessen Vorteile nicht willst?
Das frage ich mich genauso wie Tobias.

Und warum Arduino Hardware, statt eines atmega 328 chip ?
PB1 (PortB Bit1) ist übrigens beim 168 oder 328 Hardware Pin 15 ( beim Arduino UNO Pin 9 genannt )


Nachtrag:
*)
Arduino Blink für 328 sind immerhin gut 500 Byte mehr ( oder doppelt so groß ), im Vergleich zu direkter PORT Manipulation und mit <util/delay.h>

Das ist ehr eine interessensfrage gewesen.

So gut kann ich nicht programmieren, aber um mal ein C beispiel zu testen, und man das direkt in der IDE kann reicht mir

außerdem soll es ja auch funktionen geben die bei Arduino sehr komplex sind und in normal C einfacher wären

könnte man theoretisch auch mischen?

Also arduino und eine komplexe funktion dann in normalen C?

könnte man theoretisch auch mischen?

klar.

Das oben ist schon eine Mischung, und verwendet void main() aus der Arduino IDE.
In der Praxis macht man das, wenn z.B. analogRead() mit seinen 120µs / Messung zu langsam ist, und man Funktionen verwenden will, die so in der Arduino IDE nicht vorhanden sind.
Oder wenn man die vorhandenen Counter anders als für Standard PWM mit analogWrite(pin,wert); nutzen will.

Mit “C Beispiel” meinst du wohl so geheimnisvolle Sachen wie

    PORTB &= ~(1<<PB1);   // Bit loeschen

das ist auch nicht “mehr C” als

   digitalWrite(9,LOW);

Im einen Fall ist eben PORTB und PB1 irgendwo anders definiert,
im anderen Fall LOW und die Funktion digitalWrite().
Die Programmiersprache C ist die gleiche.

Das erste ist ein bisschen näher an der aktuellen Hardware,
Das andere hat den Vorteil, dass die LED auf einem Shield sitzen kann, das man sowohl auf einen UNO wie auf einen MEGA2560 stecken kann und du das Programm nicht ändern musst.

In beiden Versionen kannst du LED’s so schnell schalten, dass du es nicht flackern siehst. :wink:

Hallo,
“PORTB &= ~(1<<PB1)
digitalWrite(9,LOW)”

wenn ich so etwas lese… was bringt es beim Arduino denn wirklich?
Oben gebe ich 16 Zeichen ein, unten 19 Zeichen.
Gut, bei 10 versiedenen Aufrufen sind das 30 Zeichen, das macht den Code
“extern” 30 Zeichen kürzer, und weniger “getippe”.
Intern wird das von der IDE doch gleich behandelt? Und bei der Ausführungs-
geschwindigkeit ändert sich doch nichts? Die IDE behandelt doch beides
gleich?
Gruß und Spaß
Andreas

Wie viele Buchstaben man zum Programmieren braucht, ist ein sehr schönes Kriterium ;) ( Wie viel Kommentar ist erforderlich, damit der Code verständlich bleibt ?)

Das Blink Beispiel ist zwar nur halb so groß, aber im Endeffekt bringt es nichts, das sehe ich auch so.

Wenn du damit nicht blinken, sondern was schnelleres machen willst, wirst du mit direkter PORT Manipulation ein bisschen schneller, noch erheblich weiter kommst du mit direkter Timer-Programmierung, und da macht dann digitalWrite innerhalb der Timer-Routine keinen Sinn mehr.

Hallo, da wird mir ja etwas klar, "direkter PORT Manipulation" gleich direkte Manipulation. Deswegen wird der Arduino in manchen "hochtrabenen HochsprachenForen auch "leise belächelt"… Weil sie meinen, das sie mit ihrer bitFrimeleih schneller und sicherer sind. Das trifft dann aber nur auf ganz spezielle Fälle zu. Aber wann brauche ich das als "privater" tatsächlich"? Schönen Dank Andreas

Wenn was schnell sein muss, bringt das viel. Multiplexen von LED Matrizen zum Beispiel. Oder schnelle Interrupt-Routinen, wenn man was schnell messen muss. Das ist etwa 25 mal schneller als digitalWrite(). Das ist auf keinen Fall das gleiche!! digitalWrite() muss die Arduino Port Nummern auf die Prozessor Pins umsetzen und führt Plausibilitätsüberprüfung durch. Das kostet Zeit:
http://www.billporter.info/2010/08/18/ready-set-oscillate-the-fastest-way-to-change-arduino-pins/

Es gibt eine digitalWriteFast Lib mit der man mit etwas Arduino-ähnlichem auf die gleiche Geschwindigkeit kommt. Aber nur wenn der Pin zur Compile-Zeit fest steht. Das ist auch nicht schlecht. Außerdem kann man sich für sowas Makros definieren, damit es lesbarer wird:

#define BIT_CLR(x,y) (x&=(~(1<<y)))
#define BIT_SET(x,y) (x|=(1<<y))

Und schon kann man es wie eine Funktion verwenden

Und man kann 8 Bits auf einmal setzen. Manchmal ist daher einfach wesentlich besser lesbarer “PORTB = val” zu schreiben als 8 mal digitalWrite() oder digitalRead() zu machen.

Noch einen Takt schneller toggelt man ein Bit übrigens wenn man eine 1 auf das Port-Eingangsregister PINn schreibt :wink:

Es gibt einiges an Sachen bei denen man von den Arduino-Mittel loskommen muss. Der ADC ist auch so ein Fall. Der hat zig mal mehr Funktionen als die Arduino IDE unterstützt. Und dann natürlich Timer.